twat 0.6.3 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.rvmrc +1 -1
  2. data/.travis.yml +6 -0
  3. data/Gemfile +1 -4
  4. data/Gemfile.lock +43 -23
  5. data/Gemfile.travis +12 -0
  6. data/Rakefile +9 -0
  7. data/TODO +4 -1
  8. data/lib/twat.rb +30 -26
  9. data/lib/twat/argparse.rb +36 -79
  10. data/lib/twat/config.rb +22 -34
  11. data/lib/twat/endpoint.rb +11 -5
  12. data/lib/twat/endpoints/base.rb +39 -0
  13. data/lib/twat/endpoints/identica.rb +5 -1
  14. data/lib/twat/endpoints/twitter.rb +5 -1
  15. data/lib/twat/exceptions.rb +93 -46
  16. data/lib/twat/follow_mixin.rb +134 -0
  17. data/lib/twat/options.rb +28 -12
  18. data/lib/twat/subcommand.rb +34 -0
  19. data/lib/twat/subcommands/add.rb +17 -0
  20. data/lib/twat/subcommands/base.rb +122 -0
  21. data/lib/twat/subcommands/config.rb +15 -0
  22. data/lib/twat/subcommands/delete.rb +24 -0
  23. data/lib/twat/subcommands/finger.rb +23 -0
  24. data/lib/twat/subcommands/follow.rb +18 -0
  25. data/lib/twat/subcommands/follow_tag.rb +19 -0
  26. data/lib/twat/subcommands/list.rb +17 -0
  27. data/lib/twat/subcommands/mentions.rb +20 -0
  28. data/lib/twat/subcommands/set.rb +19 -0
  29. data/lib/twat/subcommands/track.rb +33 -0
  30. data/lib/twat/subcommands/update.rb +21 -0
  31. data/lib/twat/subcommands/update_config.rb +16 -0
  32. data/lib/twat/subcommands/version.rb +14 -0
  33. data/lib/twat/twatopt.rb +0 -0
  34. data/lib/twat/tweetstack.rb +38 -0
  35. data/lib/twat/version.rb +7 -0
  36. data/man/twat.1 +8 -5
  37. data/spec/argparse_spec.rb +48 -0
  38. data/spec/helpers/environment.rb +47 -0
  39. data/spec/helpers/fileutils.rb +18 -0
  40. data/spec/helpers/fixtures/core.rb +30 -0
  41. data/spec/helpers/fixtures/migrations.rb +13 -0
  42. data/spec/helpers/oauth.rb +15 -0
  43. data/spec/spec_helper.rb +13 -0
  44. data/spec/subcommands/add_spec.rb +61 -0
  45. data/spec/subcommands/config_spec.rb +13 -0
  46. data/spec/subcommands/delete_spec.rb +12 -0
  47. data/spec/subcommands/finger_spec.rb +41 -0
  48. data/spec/subcommands/follow_spec.rb +12 -0
  49. data/spec/subcommands/follow_tag_spec.rb +52 -0
  50. data/spec/subcommands/list_spec.rb +8 -0
  51. data/spec/subcommands/mentions_spec.rb +24 -0
  52. data/spec/subcommands/set_spec.rb +126 -0
  53. data/spec/subcommands/track_spec.rb +23 -0
  54. data/spec/subcommands/update_config_spec.rb +23 -0
  55. data/spec/subcommands/update_spec.rb +12 -0
  56. data/spec/subcommands/version_spec.rb +12 -0
  57. data/spec/twat_cli_spec.rb +102 -0
  58. data/spec/twat_spec.rb +12 -0
  59. data/twat.gemspec +6 -2
  60. metadata +135 -22
  61. data/lib/twat/actions.rb +0 -85
  62. data/lib/twat/actions/add.rb +0 -36
  63. data/lib/twat/actions/delete.rb +0 -14
  64. data/lib/twat/actions/follow.rb +0 -148
  65. data/lib/twat/actions/follow_user.rb +0 -11
  66. data/lib/twat/actions/setoption.rb +0 -14
  67. data/lib/twat/actions/show.rb +0 -12
  68. data/lib/twat/actions/tweet.rb +0 -14
  69. data/lib/twat/actions/updateconfig.rb +0 -9
  70. data/lib/twat/actions/user_feed.rb +0 -17
  71. data/lib/twat/actions/version.rb +0 -9
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.3
1
+ rvm use 1.9.3
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ gemfile: Gemfile.travis
3
+ rvm:
4
+ # - 1.8.7
5
+ - 1.9.2
6
+ - 1.9.3
data/Gemfile CHANGED
@@ -1,5 +1,2 @@
1
1
  source :rubygems
2
-
3
- gem "twitter"
4
- gem "oauth"
5
- gem "rack", '1.3.3'
2
+ gemspec
@@ -1,31 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ twat (0.9.1)
5
+ oauth
6
+ readline-ng (>= 0.0.8)
7
+ twitter
8
+
1
9
  GEM
2
10
  remote: http://rubygems.org/
3
11
  specs:
4
- addressable (2.2.6)
5
- faraday (0.7.4)
6
- addressable (~> 2.2.6)
7
- multipart-post (~> 1.1.0)
8
- rack (>= 1.1.0, < 2)
9
- faraday_middleware (0.7.0)
10
- faraday (~> 0.7.3)
11
- hashie (1.1.0)
12
- multi_json (1.0.3)
13
- multi_xml (0.2.2)
14
- multipart-post (1.1.3)
15
- oauth (0.4.5)
16
- rack (1.3.2)
17
- simple_oauth (0.1.5)
18
- twitter (1.6.2)
19
- faraday (~> 0.7.4)
20
- faraday_middleware (~> 0.7.0)
21
- hashie (~> 1.1.0)
22
- multi_json (~> 1.0.0)
23
- multi_xml (~> 0.2.0)
24
- simple_oauth (~> 0.1.5)
12
+ activesupport (3.2.3)
13
+ i18n (~> 0.6)
14
+ multi_json (~> 1.0)
15
+ diff-lcs (1.1.3)
16
+ faraday (0.8.0)
17
+ multipart-post (~> 1.1)
18
+ i18n (0.6.0)
19
+ metaclass (0.0.1)
20
+ mktemp (0.0.1)
21
+ mocha (0.11.3)
22
+ metaclass (~> 0.0.1)
23
+ multi_json (1.3.2)
24
+ multipart-post (1.1.5)
25
+ oauth (0.4.6)
26
+ rake (0.9.2.2)
27
+ readline-ng (0.0.8)
28
+ rspec (2.9.0)
29
+ rspec-core (~> 2.9.0)
30
+ rspec-expectations (~> 2.9.0)
31
+ rspec-mocks (~> 2.9.0)
32
+ rspec-core (2.9.0)
33
+ rspec-expectations (2.9.1)
34
+ diff-lcs (~> 1.1.3)
35
+ rspec-mocks (2.9.0)
36
+ simple_oauth (0.1.7)
37
+ twitter (2.2.4)
38
+ activesupport (>= 2.3.9, < 4)
39
+ faraday (~> 0.8)
40
+ multi_json (~> 1.3)
41
+ simple_oauth (~> 0.1.6)
25
42
 
26
43
  PLATFORMS
27
44
  ruby
28
45
 
29
46
  DEPENDENCIES
30
- oauth
31
- twitter
47
+ mktemp
48
+ mocha
49
+ rake
50
+ rspec
51
+ twat!
@@ -0,0 +1,12 @@
1
+ source :rubygems
2
+
3
+ gem "twitter"
4
+ gem "oauth"
5
+ gem "readline-ng", ">= 0.0.4"
6
+ group :test do
7
+ gem "rake"
8
+ gem "mocha"
9
+ gem "rspec"
10
+ gem "mktemp"
11
+ end
12
+
@@ -0,0 +1,9 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.pattern = "spec/**/*_spec.rb"
6
+ end
7
+
8
+ desc 'Default: run specs'
9
+ task :default => :spec
data/TODO CHANGED
@@ -5,7 +5,6 @@ COLORS!
5
5
 
6
6
  Refactor tweet printing code, unify throughout
7
7
 
8
-
9
8
  TODO
10
9
  ====
11
10
 
@@ -45,6 +44,10 @@ Allow -f #hashtag to follow that hashtag instead of your newsfeed
45
44
 
46
45
  Seriously consider moving to subcommands
47
46
 
47
+ Still needs argv parsing for account etc
48
+
49
+ twat config to create the first account from scratch
50
+
48
51
  MOAR BACKENDS
49
52
  =============
50
53
 
@@ -5,18 +5,20 @@ require 'twitter'
5
5
  require 'yaml'
6
6
  require 'optparse'
7
7
  require 'oauth'
8
+ require 'readline-ng'
8
9
 
9
- %w[config exceptions argparse actions migration options endpoint].each do |filename|
10
+ %w[follow_mixin endpoint exceptions config argparse migration options
11
+ subcommand version tweetstack].each do |filename|
10
12
  require "twat/#{filename}"
11
13
  end
12
14
 
13
- %w[follow tweet add delete follow_user updateconfig setoption show user_feed version].each do |filename|
14
- require "twat/actions/#{filename}"
15
- end
16
-
17
15
  class String
18
16
  # TODO - It'd be nice to implement the colors support here, maybe even only
19
17
  # mix this in if it's enabled?
18
+ def black
19
+ "#{self}"
20
+ end
21
+
20
22
  def red
21
23
  "#{self}"
22
24
  end
@@ -44,33 +46,35 @@ class String
44
46
  def mentions?(name)
45
47
  return self.downcase.include?(name.to_s.downcase)
46
48
  end
47
- end
48
49
 
49
- module Twat
50
- VERSION_MAJOR = 0
51
- VERSION_MINOR = 6
52
- VERSION_PATCH = 3
53
-
54
- VERSION = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_PATCH}"
55
- class Twat
50
+ def colorise!
51
+ colorise_handles!
52
+ colorise_hashtags!
53
+ colorise_urls!
54
+ end
56
55
 
57
- include HandledExceptions
56
+ def colorise_handles!
57
+ self.gsub!(/@[a-z0-9_+-]+/i) { |s| s.cyan }
58
+ return self
59
+ end
58
60
 
59
- def cli_run
60
- # FIXME Handing in the opts like this feels dirty
61
- with_handled_exceptions(ArgParse.new) do |opts|
62
- if opts[:account] && opts[:action] != :add
63
- config.account = opts[:account]
64
- end
61
+ def colorise_hashtags!
62
+ self.gsub!(/#[a-z0-9_+-]+/i) { |s| s.cyan }
63
+ return self
64
+ end
65
65
 
66
- require 'readline-ng'
67
- actor = Actions.new
66
+ def colorise_urls!
67
+ self.gsub!(%r{https?://[a-z0-9./_+-]+}i) { |s| s.black }
68
+ return self
69
+ end
70
+ end
68
71
 
72
+ module Twat
73
+ class Twat
69
74
 
70
- actor.config = config
71
- actor.opts = opts
72
- actor.send(opts.options[:action])
73
- end
75
+ def cli_run
76
+ # FIXME exception handling is gone for now
77
+ Subcommand.run
74
78
  end
75
79
  end
76
80
  end
@@ -1,10 +1,36 @@
1
1
  module Twat
2
- REQUIRED = []
3
- MSG_REQUIRED = [:tweet]
2
+ class ArgWrapper
3
+ def initialize(data)
4
+ @data = data
5
+ end
4
6
 
5
- class ArgParse
7
+ def method_missing(sym)
8
+ @data[sym]
9
+ end
10
+ end
6
11
 
12
+ class Args
7
13
  # TODO delegate specifically instead of shimming everything?
14
+ # TODO Twat::Subcommands.COMMANDS needs to be parsed and dumped
15
+
16
+ def initialize
17
+ # XXX What the shit...
18
+ getopts
19
+ end
20
+
21
+ def method_missing(sym)
22
+ @options[sym]
23
+ end
24
+
25
+ def [](key)
26
+ @options[key]
27
+ end
28
+
29
+ def include?(key)
30
+ @options.include?(key)
31
+ end
32
+
33
+ private
8
34
 
9
35
  def usage(additional=nil)
10
36
  puts additional if additional
@@ -14,100 +40,31 @@ module Twat
14
40
 
15
41
  def getopts
16
42
  options = Hash.new
17
- options[:count] = 1
18
43
  @optparser = OptionParser.new do |opts|
19
44
  opts.banner = "Usage: twat <tweet>"
20
45
 
21
46
  opts.on('-n', '--account ACCOUNT', 'Use ACCOUNT (or default)') do |acct| #{{{ --account ACCOUNT
22
47
  options[:account] = acct.to_sym
23
48
  end # }}}
24
- opts.on('-a', '--add ACCOUNT', 'Configure and authorise ACCOUNT') do |acct| #{{{ --add ACCOUNT
25
- options[:account] = acct.to_sym
26
- options[:action] = :add
27
- end #}}}
28
- opts.on('--follow-user USER', 'Follow USER on twitter') do |user| #{{{ --follow-user USER
29
- options[:action] = :follow_user
30
- options[:user] = user
31
- end #}}}
32
- opts.on('--endpoint ENDPOINT', 'Specify a different endpoint for use with --add') do |endpoint| #{{{ --add ACCOUNT
49
+ opts.on('--endpoint ENDPOINT', 'Specify a different endpoint for use with add or config') do |endpoint| #{{{ --add ACCOUNT
33
50
  options[:endpoint] = endpoint.to_sym
34
51
  end #}}}
35
- opts.on('-d', '--delete ACCOUNT', 'Delete ACCOUNT') do |acct| #{{{ --delete ACCOUNT
36
- options[:account] = acct.to_sym
37
- options[:action] = :delete
38
- end #}}}
39
52
  opts.on('-h', '--help', 'Display this screen') do #{{{ --help
40
53
  puts opts
41
54
  exit
42
55
  end #}}}
43
- opts.on('-l', '--list [COUNT]', 'Display [count] tweets from your newsfeed') do |count| #{{{ --list ACCOUNT
44
- options[:count] = count || 10
45
- options[:action] ||= :show
46
- end #}}}
47
- opts.on('-f', '--follow', 'Display tweets from your newsfeed indefinitely') do #{{{ --follow
48
- options[:action] = :follow
49
- end #}}}
50
56
  opts.on('-v', '--version', 'Display version info') do #{{{ --version
51
- options[:action] = :version
52
- end #}}}
53
- opts.on('-u', '--user [USER]', 'Display current status for USER (Defaults to your default account)') do |user| #{{{ --user USER
54
- options[:user] = (user || :default)
55
- options[:action] = :user_feed
56
- end #}}}
57
- opts.on("--set OPTION=VALUE", 'Set OPTION to VALUE') do |optval| #{{{ --set OPTION=VALUE
58
- options[:action] = :setoption
59
- options[:optval] = optval
60
- end #}}}
61
- opts.on("--update-config", "Update config to latest version") do #{{{ --update-config
62
- options[:action] = :updateconfig
57
+ # FIXME, this is /bad/
58
+ puts "twat #{::Twat::VERSION}"
59
+ exit
63
60
  end #}}}
64
61
  end
65
62
  @optparser.parse!
66
- # {{{ Validation ---
67
- # Default action is to send a tweet
68
- options[:action] ||= :tweet
69
-
70
- # Only specify an endpoint when adding accounts
71
- if options[:endpoint]
72
- usage unless options[:action] == :add
73
- end
74
- # Similarly, default endpoint to twitter when we do add
75
- if options[:action] == :add
76
- options[:endpoint] ||= :twitter
77
- end
78
-
79
- REQUIRED.each do |req|
80
- usage unless options[req]
81
- end
82
- if MSG_REQUIRED.include?(options[:action])
83
- options[:msg] = msg
84
- end
85
- # }}} Validation End ---
86
- options
87
- end
88
-
89
- def msg
90
- usage unless ARGV.length > 0
91
- ARGV.join(" ")
92
- end
93
-
94
- def [](key)
95
- options[key]
96
- end
97
63
 
98
- def include?(key)
99
- options.include?(key)
100
- end
64
+ # Only makes sense for add, but doesn't hurt anything else
65
+ options[:endpoint] ||= :twitter
101
66
 
102
- def options
103
- begin
104
- @configthingfucken ||= getopts
105
- # FIXME, actually do something smart, not yell and barf
106
- rescue OptionParser::InvalidOption
107
- usage "Unknown option"
108
- rescue OptionParser::MissingArgument
109
- usage "Missing argument"
110
- end
67
+ @options = options
111
68
  end
112
69
 
113
70
  end
@@ -1,21 +1,19 @@
1
1
  module Twat
2
- class Twat
3
- def configure(&block)
4
- yield config
2
+ class Config
5
3
 
6
- # If I understand correctly, I can check over what's
7
- # happened here?
8
- end
4
+ include ::Twat::Exceptions
9
5
 
10
- def config
11
- @config ||= Config.new
6
+ def config_path
7
+ @config_path ||= ENV['TWAT_CONFIG'] || "#{ENV['HOME']}/.twatrc"
12
8
  end
13
- end
14
9
 
15
- class Config
10
+ def exists?
11
+ File.exist?(config_path)
12
+ end
16
13
 
17
- def config_path
18
- @config_path ||= ENV['TWAT_CONFIG'] || "#{ENV['HOME']}/.twatrc"
14
+ def create!
15
+ @config = { accounts: {} }
16
+ save!
19
17
  end
20
18
 
21
19
  def create_unless_exists!
@@ -57,13 +55,15 @@ module Twat
57
55
  end
58
56
 
59
57
  def colors?
60
- colors = config[:colors] || "true"
61
- Options.bool_true?(colors)
58
+ config[:colors].nil? ? false : config[:colors]
62
59
  end
63
60
 
64
61
  def beep?
65
- beep = config[:beep] || "false"
66
- Options.bool_true?(beep)
62
+ config[:beep].nil? ? false : config[:beep]
63
+ end
64
+
65
+ def show_mentions?
66
+ config[:show_mentions].nil? ? false : config[:show_mentions]
67
67
  end
68
68
 
69
69
  def polling_interval
@@ -78,34 +78,22 @@ module Twat
78
78
  # it does this by calling a sequence of migration functions in order
79
79
  # which rebuild the config in stages, saving and leaving it in a
80
80
  # consistent step at each point
81
- def update!
81
+ def update_config
82
+ raise NoConfigFile unless exists?
82
83
  Migrate.new.migrate!(config_path)
83
84
  end
84
85
 
85
- # I don't know how rubyists feel about method returning something vastly
86
- # different to what method= accepts, but I think the api makes sense
87
- def account=(acct)
88
- if accounts.include?(acct)
89
- @account = acct
90
- else
91
- raise NoSuchAccount
92
- end
93
- end
94
-
95
- def account_set?
96
- !!@account
97
- end
98
-
99
86
  def account_name
100
- if account_set?
101
- @account
87
+ if $args[:account]
88
+ return $args[:account].to_sym
102
89
  else
103
- raise NoDefaultAccount unless config.include?(:default)
90
+ raise ::Twat::Exceptions::NoDefaultAccount unless config.include?(:default)
104
91
  return config[:default].to_sym
105
92
  end
106
93
  end
107
94
 
108
95
  def account
96
+ raise NoSuchAccount unless accounts.include?(account_name)
109
97
  accounts[account_name]
110
98
  end
111
99