termtter 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
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