termtter 1.6.0 → 1.7.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.
Files changed (98) hide show
  1. data/.gitignore +5 -0
  2. data/README.rdoc +2 -2
  3. data/Rakefile +41 -75
  4. data/VERSION +1 -0
  5. data/bin/termtter +9 -2
  6. data/doc/Termtter-1.0-Release-Note-English.txt +37 -0
  7. data/doc/Termtter-1.0-Release-Note.txt +37 -0
  8. data/lib/plugins/another_prompt.rb +8 -8
  9. data/lib/plugins/ar.rb +102 -0
  10. data/lib/plugins/async.rb +1 -1
  11. data/lib/plugins/babelfish.rb +34 -0
  12. data/lib/plugins/confirm.rb +2 -0
  13. data/lib/plugins/crypt.rb +44 -0
  14. data/lib/plugins/defaults/auto_reload.rb +1 -1
  15. data/lib/plugins/defaults/command_line.rb +34 -17
  16. data/lib/plugins/defaults/confirm.rb +30 -0
  17. data/lib/plugins/defaults/hashtag.rb +1 -1
  18. data/lib/plugins/defaults/irb.rb +30 -0
  19. data/lib/plugins/defaults/keyword.rb +58 -0
  20. data/lib/plugins/defaults/list.rb +155 -0
  21. data/lib/plugins/defaults/plugin.rb +59 -0
  22. data/lib/plugins/defaults/retweet.rb +75 -23
  23. data/lib/plugins/defaults/standard_commands.rb +60 -87
  24. data/lib/plugins/defaults/standard_completion.rb +25 -15
  25. data/lib/plugins/defaults/stdout.rb +49 -10
  26. data/lib/plugins/defaults/switch.rb +1 -1
  27. data/lib/plugins/defaults/users.rb +63 -0
  28. data/lib/plugins/draft.rb +58 -0
  29. data/lib/plugins/expand-tinyurl.rb +5 -9
  30. data/lib/plugins/favotter.rb +1 -1
  31. data/lib/plugins/footer.rb +22 -0
  32. data/lib/plugins/friends.rb +5 -4
  33. data/lib/plugins/g.rb +9 -16
  34. data/lib/plugins/gem_install.rb +24 -0
  35. data/lib/plugins/gist.rb +20 -0
  36. data/lib/plugins/grass.rb +1 -1
  37. data/lib/plugins/gyazo.rb +78 -0
  38. data/lib/plugins/http_server.rb +1 -1
  39. data/lib/plugins/hugeurl.rb +6 -13
  40. data/lib/plugins/irc_gw.rb +15 -11
  41. data/lib/plugins/me.rb +1 -1
  42. data/lib/plugins/notify-send.rb +1 -1
  43. data/lib/plugins/notify-send3.rb +1 -1
  44. data/lib/plugins/open.rb +1 -1
  45. data/lib/plugins/open_url.rb +5 -1
  46. data/lib/plugins/pool.rb +1 -1
  47. data/lib/plugins/random.rb +1 -1
  48. data/lib/plugins/reply_retweet.rb +42 -0
  49. data/lib/plugins/screen-notify.rb +1 -1
  50. data/lib/plugins/sl.rb +3 -3
  51. data/lib/plugins/storage.rb +7 -10
  52. data/lib/plugins/storage/sqlite3.rb +155 -0
  53. data/lib/plugins/storage/status.rb +2 -0
  54. data/lib/plugins/stream.rb +1 -1
  55. data/lib/plugins/tinyurl.rb +3 -9
  56. data/lib/plugins/trends.rb +2 -2
  57. data/lib/plugins/truncate.rb +1 -1
  58. data/lib/plugins/w3mimg.rb +1 -1
  59. data/lib/termtter.rb +19 -20
  60. data/lib/termtter/active_rubytter.rb +4 -0
  61. data/lib/termtter/api.rb +22 -5
  62. data/lib/termtter/client.rb +55 -40
  63. data/lib/termtter/command.rb +3 -2
  64. data/lib/termtter/config_setup.rb +1 -1
  65. data/lib/termtter/config_template.erb +5 -0
  66. data/lib/termtter/default_config.rb +18 -0
  67. data/lib/termtter/hookable.rb +1 -0
  68. data/lib/termtter/httppool.rb +44 -0
  69. data/lib/termtter/memory_cache.rb +32 -0
  70. data/lib/termtter/optparse.rb +8 -15
  71. data/lib/termtter/rubytter_proxy.rb +65 -4
  72. data/lib/termtter/system_extensions.rb +40 -9
  73. data/lib/termtter/task.rb +2 -1
  74. data/spec/plugins/defaults/hashtag_spec.rb +8 -7
  75. data/spec/plugins/defaults/list_spec.rb +33 -0
  76. data/spec/plugins/defaults/plugin_spec.rb +17 -0
  77. data/spec/plugins/defaults/retweet_spec.rb +205 -0
  78. data/spec/plugins/draft_spec.rb +59 -0
  79. data/spec/plugins/expand-tinyurl_spec.rb +21 -0
  80. data/spec/plugins/footer_spec.rb +50 -0
  81. data/spec/plugins/storage/sqlite3_spec.rb +41 -0
  82. data/spec/termtter/api_spec.rb +1 -1
  83. data/spec/termtter/client_spec.rb +21 -21
  84. data/spec/termtter/command_spec.rb +8 -8
  85. data/spec/termtter/config_spec.rb +2 -2
  86. data/spec/termtter/memory_cache_spec.rb +20 -0
  87. data/spec/termtter/optparse_spec.rb +1 -1
  88. data/spec/termtter/rubytter_proxy_spec.rb +38 -0
  89. data/spec/termtter/system_extensions_spec.rb +25 -23
  90. data/spec/termtter/task_manager_spec.rb +1 -1
  91. data/spec/termtter_spec.rb +4 -2
  92. metadata +88 -19
  93. data/lib/plugins/defaults/lists.rb +0 -14
  94. data/lib/plugins/irb.rb +0 -6
  95. data/lib/plugins/storage/DB.rb +0 -37
  96. data/lib/termtter/version.rb +0 -4
  97. data/spec/plugins/defaults/lists_spec.rb +0 -34
  98. data/spec/plugins/storage/DB_spec_.rb +0 -12
@@ -43,5 +43,9 @@ module Termtter
43
43
  memo
44
44
  end
45
45
  end
46
+
47
+ def retweeted_status
48
+ nil
49
+ end
46
50
  end
47
51
  end
data/lib/termtter/api.rb CHANGED
@@ -1,9 +1,26 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  config.set_default(:host, 'twitter.com')
4
- config.proxy.set_default(:port, '8080')
5
- config.proxy.set_default(:host, nil)
6
- config.proxy.set_default(:port, nil)
4
+ if ENV.has_key?('HTTP_PROXY')
5
+ require 'uri'
6
+ proxy = ENV['HTTP_PROXY']
7
+ proxy = "http://" + proxy if proxy !~ /^http:\/\//
8
+ u = URI.parse(proxy)
9
+ config.proxy.set_default(:host, u.host)
10
+ config.proxy.set_default(:port, u.port.to_s)
11
+
12
+ if u.userinfo.nil?
13
+ config.proxy.set_default(:host, nil)
14
+ config.proxy.set_default(:port, nil)
15
+ else
16
+ user_name,password = u.userinfo.split(/:/)
17
+ config.proxy.set_default(:user_name, user_name)
18
+ config.proxy.set_default(:password, password)
19
+ end
20
+ else
21
+ config.proxy.set_default(:host, nil)
22
+ config.proxy.set_default(:port, nil)
23
+ end
7
24
  config.proxy.set_default(:user_name, nil)
8
25
  config.proxy.set_default(:password, nil)
9
26
  config.set_default(:enable_ssl, false)
@@ -13,7 +30,6 @@ module Termtter
13
30
  class << self
14
31
  attr_reader :connection, :twitter
15
32
  def setup
16
-
17
33
  3.times do
18
34
  begin
19
35
  if twitter = try_auth
@@ -40,6 +56,8 @@ module Termtter
40
56
 
41
57
  if config.user_name.empty?
42
58
  config.user_name = ui.ask('Username: ')
59
+ else
60
+ puts "Username: #{config.user_name}"
43
61
  end
44
62
  if config.password.empty?
45
63
  config.password = ui.ask('Password: ') { |q| q.echo = false}
@@ -50,7 +68,6 @@ module Termtter
50
68
  twitter.verify_credentials
51
69
  return twitter
52
70
  rescue Rubytter::APIError
53
- config.__clear__(:user_name)
54
71
  config.__clear__(:password)
55
72
  end
56
73
  return nil
@@ -15,12 +15,6 @@ module Termtter
15
15
  @filters = []
16
16
  @since_id = nil
17
17
 
18
- config.set_default(:logger, nil)
19
- config.set_default(:update_interval, 120)
20
- config.set_default(:prompt, '> ')
21
- config.set_default(:devel, false)
22
- config.set_default(:timeout, 5)
23
-
24
18
  Thread.abort_on_exception = true
25
19
 
26
20
  class << self
@@ -33,6 +27,11 @@ module Termtter
33
27
  name.each {|i| plug(i, options) }
34
28
  return
35
29
  end
30
+
31
+ name = name.to_s
32
+
33
+ return if config.system.disable_plugins.include?(name.gsub('defaults/', ''))
34
+
36
35
  options.each do |key, value|
37
36
  config.plugins.__refer__(name.gsub(/-/, '_').to_sym).__assign__(key.to_sym, value)
38
37
  end
@@ -93,7 +92,7 @@ module Termtter
93
92
  def register_macro(name, macro, options = {})
94
93
  command = {
95
94
  :name => name.to_sym,
96
- :exec_proc => lambda {|arg| call_commands(macro % arg)}
95
+ :exec_proc => lambda {|arg| execute(macro % arg)}
97
96
  }.merge(options)
98
97
  register_command(command)
99
98
  end
@@ -137,11 +136,8 @@ module Termtter
137
136
  }
138
137
  end
139
138
 
140
- def call_commands(text)
141
- # status
142
- # 0: done
143
- # 1: canceled
144
- status = 0
139
+ def execute(text)
140
+ text = text.strip
145
141
 
146
142
  @task_manager.invoke_and_wait do
147
143
  # FIXME: This block can become Maybe Monad
@@ -151,29 +147,30 @@ module Termtter
151
147
  }
152
148
  return if text.empty?
153
149
 
154
- commands = find_commands(text)
155
- raise CommandNotFound, text if commands.empty?
156
-
157
- commands.each do |command|
158
- command_str, command_arg = command.split_command_line(text)
159
-
160
- modified_arg = command_arg
161
- # FIXME: This block can become Maybe Monad
162
- get_hooks("modify_arg_for_#{command.name.to_s}").each {|hook|
163
- break if modified_arg == false # interrupt if hook return false
164
- modified_arg = hook.call(command_str, modified_arg)
165
- }
166
-
167
- begin
168
- call_hooks("pre_exec_#{command.name.to_s}", command, modified_arg)
169
- result = command.call(command_str, modified_arg, text) # exec command
170
- call_hooks("post_exec_#{command.name.to_s}", command_str, modified_arg, result)
171
- rescue CommandCanceled
172
- status = 1
173
- end
150
+ command = find_command(text)
151
+ raise CommandNotFound, text unless command
152
+
153
+ command_str, modified_arg = command.split_command_line(text)
154
+ command_str.strip!
155
+ modified_arg ||= ''
156
+
157
+ # FIXME: This block can become Maybe Monad
158
+ get_hooks("modify_arg_for_#{command.name.to_s}").each {|hook|
159
+ break if modified_arg == false # interrupt if hook return false
160
+ modified_arg.strip!
161
+ modified_arg = hook.call(command_str, modified_arg) || ''
162
+ }
163
+ modified_arg.strip!
164
+
165
+ begin
166
+ call_hooks("pre_exec_#{command.name.to_s}", command, modified_arg)
167
+ result = command.call(command_str, modified_arg, text) # exec command
168
+ call_hooks("post_exec_#{command.name.to_s}", command_str, modified_arg, result)
169
+ call_hooks("post_command", text)
170
+ rescue CommandCanceled
171
+ return false
174
172
  end
175
- call_hooks("post_command", text)
176
- status
173
+ return true
177
174
  end
178
175
  rescue TimeoutError
179
176
  call_hooks("timeout", text)
@@ -184,8 +181,12 @@ module Termtter
184
181
  @commands.values.any? {|command| command.match?(text) }
185
182
  end
186
183
 
187
- def find_commands(text)
188
- @commands.values.select {|command| command.match?(text) }
184
+ def find_command(text)
185
+ @commands.
186
+ values.
187
+ select {|command| command.match?(text) }.
188
+ sort_by {|command| command.name.to_s.split(' ').size }.
189
+ last
189
190
  end
190
191
 
191
192
  def pause
@@ -235,11 +236,13 @@ module Termtter
235
236
  end
236
237
 
237
238
  def logger
238
- @logger
239
+ @logger || setup_logger
239
240
  end
240
241
 
241
242
  def setup_logger
242
243
  @logger = config.logger || default_logger
244
+ @logger.level = config.devel ? Logger::DEBUG : Logger::INFO
245
+ @logger
243
246
  end
244
247
 
245
248
  def default_logger
@@ -282,9 +285,18 @@ module Termtter
282
285
  @task_manager = Termtter::TaskManager.new(1)
283
286
  end
284
287
 
288
+ def parse_options
289
+ Termtter::OptParser.parse!(ARGV)
290
+ end
291
+
292
+ def show_splash
293
+ puts TermColor.parse(config.splash)
294
+ end
295
+
285
296
  def run
297
+ show_splash
298
+ parse_options()
286
299
  load_config()
287
- setup_logger()
288
300
  setup_task_manager()
289
301
  load_plugins()
290
302
  eval_init_block()
@@ -298,12 +310,15 @@ module Termtter
298
310
  end
299
311
  end
300
312
 
301
- config.system.run_commands.each {|cmd| call_commands(cmd) }
313
+ config.system.run_commands.each {|cmd| execute(cmd) }
302
314
 
303
315
  unless config.system.cmd_mode
304
316
  @task_manager.run()
305
317
  call_hooks(:initialize)
306
- call_hooks(:launched)
318
+ add_task(:name => :call_hooks_after_launched, :after => 1) do
319
+ call_hooks(:launched)
320
+ end
321
+ call_hooks(:init_command_line)
307
322
  end
308
323
  end
309
324
 
@@ -37,6 +37,7 @@ module Termtter
37
37
 
38
38
  # complement :: String -> [String]
39
39
  def complement(input)
40
+ input = input.sub(/^\s*/, '')
40
41
  if match?(input) && input =~ /^[^\s]+\s/
41
42
  if completion_proc
42
43
  command_str, command_arg = split_command_line(input)
@@ -45,7 +46,7 @@ module Termtter
45
46
  []
46
47
  end
47
48
  else
48
- [name.to_s, aliases.to_s].grep(/^#{Regexp.quote(input)}/)
49
+ []
49
50
  end
50
51
  end
51
52
 
@@ -95,7 +96,7 @@ module Termtter
95
96
  def split_command_line(line)
96
97
  command_words_count = command_words.size
97
98
  parts = line.strip.split(/\s+/, command_words_count + 1)
98
- [parts[0...command_words_count].join(' '), parts[command_words_count]]
99
+ [parts[0...command_words_count].join(' '), parts[command_words_count] || '']
99
100
  end
100
101
  end
101
102
  end
@@ -12,7 +12,7 @@ module Termtter
12
12
  plugins = Dir.glob(File.expand_path(File.dirname(__FILE__) + "/../plugins/*.rb")).map {|f|
13
13
  f.match(%r|lib/plugins/(.*?).rb$|)[1]
14
14
  }
15
- standard_plugins = %w[stdout standard_commands auto_reload]
15
+ standard_plugins = %w[stdout standard_commands auto_reload defaults]
16
16
 
17
17
  template = open(File.dirname(__FILE__) + '/config_template.erb').read
18
18
  config = ERB.new(template, nil, '-').result(binding) # trim_mode => '-'
@@ -2,12 +2,17 @@
2
2
 
3
3
  config.user_name = '<%= user_name %>'
4
4
  #config.update_interval = 120
5
+ #config.timeout = 5
6
+ #config.retry = 3
5
7
  #config.enable_ssl = true
6
8
  #config.proxy.host = 'proxy host'
7
9
  #config.proxy.port = '8080'
8
10
  #config.proxy.user_name = 'proxy user'
9
11
  #config.proxy.password = 'proxy password'
10
12
 
13
+ #config.plugins.keyword.keywords = ["ruby", "termtter"]
14
+ #config.plugins.stdout.colors = (31..36).to_a + (91..96).to_a
15
+
11
16
  Termtter::Client.init do |t|
12
17
  <%- (plugins - standard_plugins).each do |plugin| -%>
13
18
  # t.plug '<%= plugin %>'
@@ -0,0 +1,18 @@
1
+ config.set_default(:logger, nil)
2
+ config.set_default(:update_interval, 120)
3
+ config.set_default(:prompt, '> ')
4
+ config.set_default(:devel, false)
5
+ config.set_default(:timeout, 5)
6
+ config.set_default(:retry, 1)
7
+ config.set_default(:splash, <<SPLASH)
8
+
9
+ <cyan>&lt;(@)//_</cyan> . . <on_green> Termtter <underline>#{Termtter::VERSION}</underline> </on_green>
10
+ <cyan>\\\\</cyan> <on_green> http://termtter.org/ </on_green>
11
+
12
+ SPLASH
13
+
14
+ config.system.set_default :cmd_mode, false
15
+ config.system.set_default :run_commands, []
16
+ config.system.set_default :load_plugins, []
17
+ config.system.set_default :disable_plugins, []
18
+ config.system.set_default :eval_scripts, []
@@ -41,6 +41,7 @@ module Termtter
41
41
 
42
42
  # return last hook return value
43
43
  def call_hooks(point, *args)
44
+ Termtter::Client.logger.debug "call_hooks: [:point => #{point}, :args => [#{args.map {|a| a.inspect.split(//)[0..10].join}.join(', ')}]]"
44
45
  result = nil
45
46
  get_hooks(point).each {|hook|
46
47
  break if result == false # interrupt if hook return false
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'net/http'
3
+
4
+ module Termtter
5
+ module HTTPpool
6
+ @@connections = {}
7
+
8
+ def self.start(host, port = 80)
9
+ begin
10
+ yield(connection(host, port))
11
+ rescue EOFError
12
+ finish(host, port)
13
+ retry
14
+ end
15
+ end
16
+
17
+ def self.connection(host, port = 80)
18
+ key = connection_key(host, port)
19
+ @@connections[key] ||= http_class.start(host, port)
20
+ end
21
+
22
+ def self.finish(host, port = 80)
23
+ key = connection_key(host, port)
24
+ @@connections[key] && @@connections[key].do_finish rescue nil
25
+ @@connections.delete(key)
26
+ end
27
+
28
+ def self.connection_key(host, port)
29
+ port == 80 ? host : [host, port.to_s].join(':')
30
+ end
31
+
32
+ def self.http_class
33
+ if config.proxy.host.nil? or config.proxy.host.empty?
34
+ Net::HTTP
35
+ else
36
+ Net::HTTP::Proxy(config.proxy.host,
37
+ config.proxy.port,
38
+ config.proxy.user_name,
39
+ config.proxy.password)
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ require 'delegate'
2
+
3
+ module Termtter
4
+ class MemoryCache < SimpleDelegator
5
+ attr_reader :limit
6
+
7
+ def initialize(limit = 10000)
8
+ super(Hash.new)
9
+ @keys = []
10
+ @limit = limit
11
+ end
12
+
13
+ def adjust(key)
14
+ unless @keys.include?(key)
15
+ @keys << key
16
+ while @keys.size > limit
17
+ delete(@keys.shift)
18
+ end
19
+ end
20
+ end
21
+
22
+ def []=(key, value)
23
+ super
24
+ adjust(key)
25
+ end
26
+
27
+ def store(key, value)
28
+ super
29
+ adjust(key)
30
+ end
31
+ end
32
+ end
@@ -1,4 +1,3 @@
1
-
2
1
  module Termtter
3
2
  module OptParser
4
3
  class << self
@@ -10,39 +9,30 @@ module Termtter
10
9
  @optionparser = OptionParser.new { |opt|
11
10
  opt.program_name = 'Termtter'
12
11
 
13
- opt.on('-f', '--config-file file', 'Set path to configfile') do |val|
14
- config.system.__assign__(:conf_file, val)
15
- end
16
-
17
- opt.on('-t', '--termtter-directory directory', 'Set termtter directory') do |val|
18
- config.system.__assign__(:conf_dir, val)
19
- end
20
-
21
12
  opt.on('-d', '--devel', 'Start in developer mode') do |flg|
22
13
  config.__assign__(:devel, true) if flg
23
14
  end
24
15
 
25
- config.system.cmd_mode = false
26
16
  opt.on('-c', '--command-mode', 'Run as command mode') do |flg|
27
17
  config.system.cmd_mode = flg
28
18
  end
29
19
 
30
- config.system.run_commands = []
31
20
  opt.on('-r', '--run-command command', 'Run command') do |cmd|
32
21
  config.system.run_commands << cmd
33
22
  end
34
23
 
35
- config.system.load_plugins = []
36
24
  opt.on('-p', '--plugin plugin', 'Load plugin') do |plugin|
37
25
  config.system.load_plugins << plugin
38
26
  end
39
27
 
40
- config.system.eval_scripts = []
28
+ opt.on('-n', '--disable-plugin plugin', 'Disable plugin') do |plugin|
29
+ config.system.disable_plugins << plugin
30
+ end
31
+
41
32
  opt.on('-e', '--eval-script script', 'Eval script') do |script|
42
33
  config.system.eval_scripts << script
43
34
  end
44
35
 
45
- config.system.eval_scripts = []
46
36
  opt.on('-m', '--monochrome', 'No shell escapes for color highlightings') do |script|
47
37
  require 'termcolor'
48
38
  module ::TermColor
@@ -55,9 +45,12 @@ module Termtter
55
45
  end
56
46
  end
57
47
 
48
+ opt.on('-u', '--user user', 'Login username') do |val|
49
+ config.user_name = val
50
+ end
51
+
58
52
  opt.version = Termtter::VERSION
59
53
  }
60
-
61
54
  end
62
55
  end
63
56