termtter 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/Rakefile +15 -15
  2. data/VERSION +1 -1
  3. data/lib/plugins/appendtitle.rb +39 -19
  4. data/lib/plugins/basic.rb +25 -0
  5. data/lib/plugins/capture.rb +22 -0
  6. data/lib/plugins/channel.rb +4 -5
  7. data/lib/plugins/copy.rb +32 -0
  8. data/lib/plugins/defaults/auto_reload.rb +4 -0
  9. data/lib/plugins/defaults/cache.rb +2 -2
  10. data/lib/plugins/defaults/command_line.rb +21 -0
  11. data/lib/plugins/defaults/keyword.rb +58 -8
  12. data/lib/plugins/defaults/list.rb +6 -4
  13. data/lib/plugins/defaults/retweet.rb +6 -1
  14. data/lib/plugins/defaults/standard_commands.rb +54 -27
  15. data/lib/plugins/defaults/stdout.rb +8 -4
  16. data/lib/plugins/defaults/switch.rb +21 -9
  17. data/lib/plugins/encoding.rb +46 -0
  18. data/lib/plugins/english.rb +2 -1
  19. data/lib/plugins/friends.rb +5 -8
  20. data/lib/plugins/geo.rb +21 -0
  21. data/lib/plugins/http_server.rb +10 -3
  22. data/lib/plugins/http_server/{index.html → skin/default/index.html} +0 -0
  23. data/lib/plugins/http_server/skin/miku/cui/chara/miku/images/001.png +0 -0
  24. data/lib/plugins/http_server/skin/miku/cui/chara/miku/images/002.png +0 -0
  25. data/lib/plugins/http_server/skin/miku/cui/chara/miku/images/003.png +0 -0
  26. data/lib/plugins/http_server/skin/miku/cui/chara/miku/images/004.png +0 -0
  27. data/lib/plugins/http_server/skin/miku/cui/chara/miku/script.js +66 -0
  28. data/lib/plugins/http_server/skin/miku/cui/core.js +198 -0
  29. data/lib/plugins/http_server/skin/miku/cui/util.js +65 -0
  30. data/lib/plugins/http_server/skin/miku/index.html +142 -0
  31. data/lib/plugins/http_server/skin/miku/jquery-1.4.2.min.js +154 -0
  32. data/lib/plugins/http_server/skin/sample1/index.html +165 -0
  33. data/lib/plugins/im_kayac.rb +33 -0
  34. data/lib/plugins/irc_gw.rb +53 -17
  35. data/lib/plugins/mongo.rb +112 -0
  36. data/lib/plugins/reply_sound.rb +1 -1
  37. data/lib/plugins/say.rb +2 -1
  38. data/lib/plugins/searchline.rb +1 -1
  39. data/lib/plugins/short_logger.rb +15 -0
  40. data/lib/plugins/storage.rb +1 -1
  41. data/lib/plugins/storage/status.rb +1 -1
  42. data/lib/plugins/stream.rb +1 -3
  43. data/lib/plugins/suspend.rb +9 -0
  44. data/lib/plugins/time_signal.rb +1 -1
  45. data/lib/plugins/tinyurl.rb +17 -8
  46. data/lib/plugins/truncate.rb +13 -3
  47. data/lib/plugins/update_editor.rb +1 -1
  48. data/lib/plugins/url.rb +11 -0
  49. data/lib/plugins/user_stream.rb +76 -51
  50. data/lib/termtter.rb +1 -0
  51. data/lib/termtter/active_rubytter.rb +3 -6
  52. data/lib/termtter/api.rb +18 -8
  53. data/lib/termtter/client.rb +30 -18
  54. data/lib/termtter/command.rb +22 -13
  55. data/lib/termtter/config.rb +15 -4
  56. data/lib/termtter/config_setup.rb +17 -2
  57. data/lib/termtter/config_template.erb +1 -0
  58. data/lib/termtter/default_config.rb +3 -1
  59. data/lib/termtter/hookable.rb +3 -3
  60. data/lib/termtter/httppool.rb +10 -4
  61. data/lib/termtter/memory_cache.rb +1 -1
  62. data/lib/termtter/optparse.rb +0 -4
  63. data/lib/termtter/rubytter_proxy.rb +31 -11
  64. data/lib/termtter/system_extensions.rb +9 -1
  65. data/lib/termtter/system_extensions/core_compatibles.rb +9 -2
  66. data/lib/termtter/task_manager.rb +2 -0
  67. data/spec/plugins/capital_update_spec.rb +1 -1
  68. data/spec/plugins/cool_spec.rb +1 -1
  69. data/spec/plugins/curry_spec.rb +1 -1
  70. data/spec/plugins/db_spec.rb +1 -1
  71. data/spec/plugins/defaults/hashtag_spec.rb +1 -1
  72. data/spec/plugins/defaults/list_spec.rb +1 -1
  73. data/spec/plugins/defaults/plugin_spec.rb +1 -1
  74. data/spec/plugins/defaults/retweet_spec.rb +1 -1
  75. data/spec/plugins/draft_spec.rb +1 -1
  76. data/spec/plugins/english_spec_.rb +1 -1
  77. data/spec/plugins/expand-tinyurl_spec.rb +1 -1
  78. data/spec/plugins/fib_spec.rb +1 -1
  79. data/spec/plugins/filter_spec_.rb +1 -1
  80. data/spec/plugins/footer_spec.rb +1 -1
  81. data/spec/plugins/gsub_spec.rb +1 -1
  82. data/spec/plugins/haml_spec.rb +1 -1
  83. data/spec/plugins/hi_spec.rb +1 -1
  84. data/spec/plugins/md5pass_spec.rb +1 -1
  85. data/spec/plugins/pause_spec.rb +1 -1
  86. data/spec/plugins/primes_spec_.rb +1 -1
  87. data/spec/plugins/shell_spec.rb +1 -1
  88. data/spec/plugins/sl_spec_.rb +1 -1
  89. data/spec/plugins/spam_spec.rb +1 -1
  90. data/spec/plugins/standard_commands_spec.rb +1 -1
  91. data/spec/plugins/storage/sqlite3_spec.rb +2 -2
  92. data/spec/plugins/storage/status_spec_.rb +2 -2
  93. data/spec/plugins/tinyurl_spec.rb +1 -1
  94. data/spec/plugins/truncate_spec.rb +36 -1
  95. data/spec/plugins/whois_spec_.rb +1 -1
  96. data/spec/termtter/active_rubytter_spec.rb +1 -1
  97. data/spec/termtter/api_spec.rb +1 -1
  98. data/spec/termtter/client_spec.rb +1 -1
  99. data/spec/termtter/command_spec.rb +1 -1
  100. data/spec/termtter/config_setup_spec.rb +1 -1
  101. data/spec/termtter/config_spec.rb +9 -1
  102. data/spec/termtter/crypt_spec.rb +1 -1
  103. data/spec/termtter/event_spec.rb +1 -1
  104. data/spec/termtter/hook_spec.rb +1 -1
  105. data/spec/termtter/hookable_spec.rb +1 -1
  106. data/spec/termtter/memory_cache_spec.rb +1 -1
  107. data/spec/termtter/optparse_spec.rb +1 -1
  108. data/spec/termtter/rubytter_proxy_spec.rb +1 -1
  109. data/spec/termtter/system_extensions/windows_spec.rb +1 -1
  110. data/spec/termtter/system_extensions_spec.rb +1 -1
  111. data/spec/termtter/task_manager_spec.rb +1 -1
  112. data/spec/termtter/task_spec.rb +1 -1
  113. data/spec/termtter_spec.rb +1 -1
  114. data/termtter.gemspec +326 -0
  115. metadata +81 -149
  116. data/.gitignore +0 -5
@@ -8,6 +8,8 @@ config.plugins.retweet.set_default(
8
8
  :official_retweet, true)
9
9
  config.plugins.retweet.set_default(
10
10
  :quotetweet, false)
11
+ config.plugins.retweet.set_default(
12
+ :as_reply, false)
11
13
 
12
14
  module Termtter::Client
13
15
  def self.post_retweet(s, comment = nil)
@@ -27,13 +29,16 @@ module Termtter::Client
27
29
  rescue Rubytter::APIError # XXX: just for transition period
28
30
  if $!.to_s == 'Not found'
29
31
  Termtter::Client.logger.warn "Failed official retweet. Set twitter langage to English in https://twitter.com/account/settings or set config.plugins.retweet.official_retweet to false."
32
+ else
33
+ raise
30
34
  end
31
35
  end
32
36
  end
33
37
  comment += ' ' unless comment.nil?
34
38
  rt_or_qt = (config.plugins.retweet.quotetweet and comment) ? 'QT' : 'RT'
35
39
  text = ERB.new(config.plugins.retweet.format).result(binding)
36
- Termtter::API.twitter.update(text)
40
+ params = config.plugins.retweet.as_reply ? {:in_reply_to_status_id => s.id} : {}
41
+ Termtter::API.twitter.update(text, params)
37
42
  puts "=> #{text}"
38
43
  end
39
44
 
@@ -20,7 +20,7 @@ module Termtter::Client
20
20
  args = @since_id ? [{:since_id => @since_id}] : []
21
21
  statuses = Termtter::API.twitter.home_timeline(*args)
22
22
  unless statuses.empty?
23
- print "\e[0G" + "\e[K" unless win?
23
+ Termtter::Client.clear_line
24
24
  @since_id = statuses[0].id
25
25
  output(statuses, Termtter::Event.new(:update_friends_timeline, :type => :main))
26
26
  Readline.refresh_line if arg =~ /\-r/
@@ -47,8 +47,15 @@ module Termtter::Client
47
47
  # "u $aa msg" is likely to be a mistake of
48
48
  # "re $aa msg".
49
49
  if /^\s*\d+\s/ =~ arg
50
- puts "Does it mean `re[ply] #{arg}`?"
51
- break
50
+ case HighLine.new.ask("Does it mean `re[ply] #{arg}` [N/y]? ")
51
+ when /^[yY]$/
52
+ Termtter::Client.execute("re #{arg}")
53
+ break
54
+ when /^[nN]?$/
55
+ else
56
+ puts "Invalid answer. Please input [yYnN] or nothing."
57
+ break
58
+ end
52
59
  end
53
60
 
54
61
  result = Termtter::API.twitter.update(arg, params)
@@ -125,7 +132,7 @@ module Termtter::Client
125
132
  end
126
133
 
127
134
  def self.get_friends(user_name, max)
128
- self.get_friends_or_followers(:followers, user_name, max)
135
+ self.get_friends_or_followers(:friends, user_name, max)
129
136
  end
130
137
 
131
138
  def self.get_followers(user_name, max)
@@ -184,7 +191,11 @@ module Termtter::Client
184
191
  }
185
192
  end
186
193
 
187
- class SearchEvent < Termtter::Event; attr_reader :query; def initialize(query); @query = query end; end
194
+ class SearchEvent < Termtter::Event
195
+ def initialize(query)
196
+ super :search, {:query => query, :type => :search}
197
+ end
198
+ end
188
199
  public_storage[:search_keywords] = Set.new
189
200
  register_command(
190
201
  :name => :search, :aliases => [:s],
@@ -309,36 +320,48 @@ module Termtter::Client
309
320
  :help => ['unblock USER', 'Unblock user']
310
321
  )
311
322
 
312
- help = ['favorite_list USERNAME', 'show user favorites']
323
+ help = ['favorites,favlist USERNAME', 'show user favorites']
313
324
  register_command(:favorites, :alias => :favlist, :help => help) do |arg|
314
- output Termtter::API.twitter.favorites(arg), :user_timeline, :type => :favorite
325
+ output(Termtter::API.twitter.favorites(arg), Termtter::Event.new(:user_timeline, :type => :favorite))
315
326
  end
316
327
 
317
328
  register_command(
318
329
  :name => :favorite, :aliases => [:fav],
319
- :exec_proc => lambda {|arg|
320
- id =
321
- case arg
322
- when /^\d+/
323
- arg.to_i
324
- when /^@([A-Za-z0-9_]+)/
325
- user_name = normalize_as_user_name($1)
326
- statuses = Termtter::API.twitter.user_timeline(user_name)
327
- return if statuses.empty?
328
- statuses[0].id
329
- when /^\/(.*)$/
330
- word = $1
331
- raise "Not implemented yet."
332
- else
333
- if public_storage[:typable_id] && typable_id?(arg)
334
- typable_id_convert(arg)
330
+ :exec_proc => lambda {|args|
331
+ args.split(' ').each do |arg|
332
+ id =
333
+ case arg
334
+ when /^\d+/
335
+ arg.to_i
336
+ when /^@([A-Za-z0-9_]+)/
337
+ user_name = normalize_as_user_name($1)
338
+ statuses = Termtter::API.twitter.user_timeline(user_name)
339
+ return if statuses.empty?
340
+ statuses[0].id
341
+ when %r{twitter.com/(?:\#!/)[A-Za-z0-9_]+/status(?:es)?/\d+}
342
+ status_id = URI.parse(arg).path.split(%{/}).last
343
+ when %r{twitter.com/[A-Za-z0-9_]+}
344
+ user_name = normalize_as_user_name(URI.parse(arg).path.split(%{/}).last)
345
+ statuses = Termtter::API.twitter.user_timeline(user_name)
346
+ return if statuses.empty?
347
+ statuses[0].id
348
+ when /^\/(.*)$/
349
+ word = $1
350
+ raise "Not implemented yet."
335
351
  else
336
- return
352
+ if public_storage[:typable_id] && typable_id?(arg)
353
+ typable_id_convert(arg)
354
+ else
355
+ return
356
+ end
337
357
  end
358
+ begin
359
+ r = Termtter::API.twitter.favorite id
360
+ puts "Favorited status ##{r.id} on user @#{r.user.screen_name} #{r.text}"
361
+ rescue => e
362
+ handle_error e
338
363
  end
339
-
340
- r = Termtter::API.twitter.favorite id
341
- puts "Favorited status ##{r.id} on user @#{r.user.screen_name} #{r.text}"
364
+ end
342
365
  },
343
366
  :completion_proc => lambda {|cmd, arg|
344
367
  case arg
@@ -507,6 +530,10 @@ module Termtter::Client
507
530
  Termtter::API.twitter.update(arg, params)
508
531
  puts "=> #{arg}"
509
532
  end
533
+ else
534
+ text = arg
535
+ last_reply = Termtter::API.twitter.replies({:count => 1}).first
536
+ update_with_user_and_id(text, last_reply.user.screen_name, last_reply.id)
510
537
  end
511
538
  },
512
539
  :completion_proc => lambda {|cmd, arg|
@@ -4,21 +4,24 @@ require 'termcolor'
4
4
  require 'erb'
5
5
  require 'tempfile'
6
6
 
7
+ config.plugins.stdout.set_default(:gray, 90)
7
8
  config.plugins.stdout.set_default(:colors, (31..36).to_a + (91..96).to_a)
8
9
  config.plugins.stdout.set_default(
9
10
  :timeline_format,
10
11
  [
11
- '<90><%=time%> [<%=status_id%>]</90> ',
12
+ '<<%=config.plugins.stdout.gray||config.plugins.stdout.colors.last%>>',
13
+ '<%=time%> [<%=status_id%>] ',
14
+ '</<%=config.plugins.stdout.gray||config.plugins.stdout.colors.last%>>',
12
15
  '<%= indent_text %>',
13
16
  '<<%=color%>><%=s.user.screen_name%>: <%=text%></<%=color%>> ',
14
- '<90>',
17
+ '<<%=config.plugins.stdout.gray||config.plugins.stdout.colors.last%>>',
15
18
  '<%=reply_to_status_id ? " (reply_to [#{reply_to_status_id}]) " : ""%>',
16
19
  '<%=retweeted_status_id ? " (retweet_to [#{retweeted_status_id}]) " : ""%>',
17
20
  '<%=source%><%=s[:user][:protected] ? "[P]" : ""%>',
18
- '</90>'
21
+ '</<%=config.plugins.stdout.gray||config.plugins.stdout.colors.last%>>',
19
22
  ].join('')
20
23
  )
21
- config.plugins.stdout.set_default(:sweets, %w[jugyo ujm sora_h lingr_termtter termtter hitode909 nanki sixeight])
24
+ config.plugins.stdout.set_default(:sweets, %w[jugyo ujm sora_h lingr_termtter termtter nanki sixeight])
22
25
  config.plugins.stdout.set_default(:sweet_color, 'red')
23
26
  config.plugins.stdout.set_default(:time_format_today, '%H:%M:%S')
24
27
  config.plugins.stdout.set_default(:time_format_not_today, '%y/%m/%d %H:%M')
@@ -120,6 +123,7 @@ module Termtter
120
123
  system "#{config.plugins.stdout.pager} #{file.path}"
121
124
  file.close(true)
122
125
  else
126
+ Termtter::Client.clear_line
123
127
  print output_text
124
128
  end
125
129
  end
@@ -10,18 +10,30 @@ module Termtter::Client
10
10
 
11
11
  passwords[config.user_name] = config.password
12
12
 
13
- if user_name
14
- config.user_name = normalize_as_user_name(arg)
15
- if passwords.key?(config.user_name)
16
- config.password = passwords[config.user_name]
17
- else
18
- config.__clear__(:password)
13
+ file_name_prefix = File.join(Termtter::CONF_DIR, config.token_file_name)
14
+ unless user_name
15
+ choices = [:new, ""]
16
+ choices += Dir.glob(file_name_prefix + "_*").map{|f| f.gsub(file_name_prefix+'_', '')}
17
+
18
+ puts "0. New user"
19
+ puts "1. Default"
20
+ choices[2..-1].each_with_index do |c, i|
21
+ puts "#{i+2}. #{c}"
22
+ end
23
+ ui = create_highline
24
+ choice = choices[ui.ask("Please choice number: ").to_i]
25
+ if choice.nil?
26
+ puts "Invalid number"
27
+ break
19
28
  end
20
- else
21
- config.__clear__(:user_name)
22
- config.__clear__(:password)
29
+ user_name = (choice == :new) ? ui.ask("Enter user name: ") : choice
23
30
  end
24
31
 
32
+ config.token_file = file_name_prefix
33
+ config.token_file += "_#{user_name}" if user_name != ""
34
+ config.__clear__(:access_token)
35
+ config.__clear__(:access_token_secret)
36
+
25
37
  Termtter::API.setup
26
38
  execute('reload')
27
39
  },
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Termtter::Client
3
+ config.plugins.encoding.set_default(:output, 'utf-8')
4
+
5
+ def self.encode text, encoding
6
+ return text unless encoding
7
+
8
+ if RUBY_VERSION >= '1.9'
9
+ begin
10
+ text = text.encode encoding
11
+ rescue
12
+ # no encodings exception
13
+ end
14
+ else
15
+ begin
16
+ require 'nkf'
17
+ rescue
18
+ return text
19
+ end
20
+
21
+ text = case encoding
22
+ when 'utf-8'
23
+ NKF.nkf('-w', text)
24
+ when 'euc-jp'
25
+ NKF.nkf('-e', text)
26
+ when 'sjis'
27
+ NKF.nkf('-s', text)
28
+ else
29
+ text
30
+ end
31
+ end
32
+ end
33
+
34
+ register_hook(
35
+ :name => :output_encoding,
36
+ :points => [:pre_output],
37
+ :exec_proc => lambda {|result, event|
38
+ result = Termtter::Client.encode result, config.plugins.encoding.output
39
+ })
40
+ register_hook(
41
+ :name => :input_encoding,
42
+ :point => /^modify_arg_for_.*/,
43
+ :exec_proc => lambda {|cmd, arg|
44
+ arg = Termtter::Client.encode arg, 'utf-8'
45
+ })
46
+ end
@@ -2,7 +2,8 @@
2
2
  # vim: set fenc=utf-8
3
3
 
4
4
  module Termtter::English
5
- # english? :: String -> Boolean
5
+ # call-seq:
6
+ # english? :: String -> Boolean
6
7
  def self.english?(message)
7
8
  /[一-龠]+|[ぁ-ん]+|[ァ-ヴー]+|[a-zA-Z0-9]+/ !~ message
8
9
  end
@@ -4,14 +4,11 @@ module Termtter::Client
4
4
  :name => :diff_follow, :aliases => [:diff],
5
5
  :exec_proc => lambda {|arg|
6
6
  user_name = arg.empty? ? config.user_name : arg
7
- friends = public_storage[:friends]
8
- followers = public_storage[:followers]
9
- if friends.nil? || followers.nil?
10
- puts 'Do followers and friends first.'
11
- return
12
- end
13
- friends = friends.map(&:screen_name)
14
- followers = followers.map(&:screen_name)
7
+ puts "getting friends"
8
+ friends = get_friends(user_name, 2000).map(&:screen_name)
9
+ puts "getting followers"
10
+ followers = get_followers(user_name, 2000).map(&:screen_name)
11
+ puts
15
12
  puts "friends - followers:"
16
13
  puts (friends - followers).map{|s|"http://#{config.host}/#{s}"}.join("\n")
17
14
  puts
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+ config.plugins.geo.set_default(:url, 'http://www.openstreetmap.org/?lat=%s&lon=%s&zoom=18')
3
+ # other setting example: 'http://maps.google.co.jp/maps?q=%s,%s'
4
+
5
+ Termtter::Client.register_hook(
6
+ :name => :geo,
7
+ :points => [:output],
8
+ :exec_proc => lambda {|statuses, event|
9
+ config.plugins.geo.path
10
+ if event == :show
11
+ statuses.each do |s|
12
+ next unless s.geo
13
+ next if s.geo[:type] != 'Point'
14
+ open_browser(config.plugins.geo.url % s.geo.coordinates)
15
+ end
16
+ end
17
+ }
18
+ )
19
+
20
+ # geo.rb:
21
+ # show the location of the tweet
@@ -12,8 +12,16 @@ require 'logger'
12
12
 
13
13
  config.plugins.http_server.set_default(:port, 5678)
14
14
  config.plugins.http_server.set_default(:reload_max_count, 100)
15
+ config.plugins.http_server.set_default(:skin, "default")
15
16
 
16
17
  module Termtter::Client
18
+ register_command(
19
+ :name => :skin,
20
+ :exec_proc => lambda {|name|
21
+ config.plugins.http_server.skin = name
22
+ }
23
+ )
24
+
17
25
  if @http_server
18
26
  @http_server.shutdown # for reload
19
27
  end
@@ -53,10 +61,9 @@ module Termtter::Client
53
61
  end
54
62
 
55
63
  @http_server.mount_proc('/') do |req, res|
64
+ skin_dir = "skin/#{config.plugins.http_server.skin}/"
56
65
  request_path = req.path == '/' ? 'index.html' : req.path
57
- base_name = Pathname.new(request_path).basename.to_s
58
- file_path = File.dirname(__FILE__) + '/http_server/' + base_name
59
-
66
+ file_path = File.dirname(__FILE__) + '/http_server/' + skin_dir + request_path.to_s
60
67
  if File.file?(file_path)
61
68
  # send a file
62
69
  res.header["Content-Type"] = MIME::Types.type_for(file_path).first.content_type
@@ -0,0 +1,66 @@
1
+ var INTERVAL = 1700;
2
+ //
3
+ // define image.
4
+ //
5
+ var 通常 = 'cui/chara/miku/images/001.png';
6
+ var 怒り = 'cui/chara/miku/images/004.png';
7
+ var 喜び = 'cui/chara/miku/images/003.png';
8
+
9
+ //
10
+ // define part.
11
+ //
12
+ var 頭 = {"left":180, "top":40, "width":100, "height":80};
13
+ var 胸 = {"left":160, "top":300, "width":120, "height":60};
14
+
15
+ //
16
+ // define actions.
17
+ //
18
+ var アクション = [
19
+ {"part":胸, "action":["touch"], "img":怒り, "msg":"Hなのはいけないと思います!"},
20
+ {"part":頭, "action":["nadenade", {"count":5}], "img":喜び, "msg":"♪〜"}
21
+ ];
22
+
23
+ $(function(){
24
+ // initialize
25
+ var sprite = new Sprite();
26
+ sprite.dlg = new Dialog(390, 70, 200, 60, '20px', "#141414", "#98FF68", '24px');
27
+ sprite.image(通常);
28
+
29
+ // regist actions.
30
+ アクション.map(function(action){
31
+ sprite[action.action[0]](action.part, action.action[1], function(e){
32
+ sprite.motion(action.img, INTERVAL);
33
+ sprite.dlg.show(action.msg, INTERVAL);
34
+ });
35
+ });
36
+
37
+ // regist main menu.
38
+ sprite.bind("dblclick", function(){
39
+ var dlg = new Dialog(390, 70, 270, 50, '20px', "#141414", "#98FF68", '24px');
40
+ var msg = $('<div id="input_area">' +
41
+ '<div id="wrap">' +
42
+ ' <form id="execute_command">' +
43
+ ' <span id="prompt">&gt; </span><input id="execute_text" type="text" size="20" autocomplete=off />' +
44
+ ' </form>' +
45
+ '</div>' +
46
+ '<div id="loading" style="display: none;">...</div></div>');
47
+
48
+ dlg.show(msg, INTERVAL * 5);
49
+ $("#execute_command").submit(function () {
50
+ var command = $("#execute_text").val();
51
+ $('<div class="status_line"/>').text('> ' + command).prependTo('#result');
52
+
53
+ cmd_history.add(command);
54
+
55
+ if (command.match(/^\s*$/)) {
56
+ return false;
57
+ }
58
+ $("#execute_text").val('');
59
+ $("#prompt").hide();
60
+ execute_command(command);
61
+
62
+ return false;
63
+ })
64
+ });
65
+ })
66
+
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Sprite Constracutor.
3
+ */
4
+ var Sprite = function(){
5
+ var obj = $("<img />").appendTo("#sprite");
6
+ obj.css('position', 'absolute').css("buttom", 0);
7
+
8
+ // regist dialog move behavor.
9
+ obj.mousedown(function(e){
10
+ obj
11
+ .data("clickPointX" , e.pageX - obj.offset().left)
12
+ .data("clickPointY" , e.pageY - obj.offset().top);
13
+
14
+ $(document).mousemove(function(e){
15
+ obj.css({
16
+ top :e.pageY - obj.data("clickPointY")+"px",
17
+ left:e.pageX - obj.data("clickPointX")+"px"
18
+ })
19
+ })
20
+ }).mouseup(function(){
21
+ $(document).unbind("mousemove")
22
+ })
23
+
24
+
25
+ /**
26
+ * proxy sprite image bind event.
27
+ */
28
+ this.bind = function(area, event_name, callback){
29
+ var x = 0;
30
+ var y = 0;
31
+
32
+ if(arguments.length == 2){
33
+ obj.bind(area, event_name);
34
+ return;
35
+ }
36
+
37
+ obj.bind("touchmove",function(e){
38
+ x = event.touches[0].pageX;
39
+ y = event.touches[0].pageY;
40
+ });
41
+ obj.bind("mousemove",function(e){
42
+ x = e.pageX;
43
+ y = e.pageY;
44
+ });
45
+
46
+ obj.bind(event_name, function(e){
47
+ if(
48
+ (area["left"] <= x && x <= (area["left"] + area["width"]) )
49
+ && (area["top"] <= y && y <= (area["top"] + area["height"]) )
50
+ ){
51
+ callback(e);
52
+ }
53
+ });
54
+ }
55
+
56
+
57
+ /**
58
+ * change sprite image.
59
+ * @params<string> image file path.
60
+ */
61
+ this.image = function(path){
62
+ obj.attr("src", path);
63
+ return this;
64
+ }
65
+
66
+ /**
67
+ * change sprite image for interval time.
68
+ * @params<string> image file path.
69
+ * @params<integer> millisecond.
70
+ */
71
+ this.motion = function(path, interval){
72
+ var current = obj.attr("src");
73
+ var self = this;
74
+ self.image(path);
75
+
76
+ setTimeout(function(){ self.image(current) } , interval);
77
+
78
+ return self;
79
+ }
80
+
81
+ /**
82
+ * touch action.
83
+ */
84
+ this.touch = function(area, args, callback){ this.bind(area, "click", callback) };
85
+
86
+ /**
87
+ * nadenade action.
88
+ */
89
+ this.nadenade = function(area, args, callback){
90
+ var step = [true].concat(array(args.count, false));
91
+ step.idx = 0;
92
+ step.isDone = function(){ return step.reduce(function(r, x){return r && x}) };
93
+ step.reset = function(){
94
+ for(var i=1;i<step.length;i++){
95
+ step[i] = false;
96
+ }
97
+ step.idx = 0;
98
+ }
99
+
100
+ var isOverPoint = function(idx, x){
101
+ var buf = 30;
102
+ var left1 = area["left"];
103
+ var left2 = left1 + buf;
104
+ var right1 = left1 + area["width"] - buf;
105
+ var right2 = right1 + buf;
106
+
107
+ return (idx % 2 == 0) ? (step[idx] && left1 <= x && x <= left2)
108
+ : (step[idx] && right1 <= x && x <= right2)
109
+ }
110
+
111
+ var action = function(x){
112
+ if (isOverPoint(step.idx, x)) {
113
+ step.idx += 1;
114
+ step[step.idx] = true;
115
+ }
116
+
117
+ if (step.isDone()) {
118
+ callback();
119
+ step.reset();
120
+ }
121
+ }
122
+
123
+ if(isTouch()){
124
+ this.bind(area, 'touchmove', function(e){
125
+ action(event.touches[0].pageX);
126
+ });
127
+ }else{
128
+ this.bind(area, 'mousemove', function(e){
129
+ action(e.pageX);
130
+ });
131
+ }
132
+ }
133
+ }
134
+
135
+
136
+ /**
137
+ * Dialog Constructor.
138
+ */
139
+ var Dialog = function(left, top, width, height, padding, bgcolor, textcolor, size){
140
+ var dlg = $("<div class='dialog'/>").appendTo("#sprite");
141
+
142
+ // setting default css.
143
+ dlg.css("display", "none")
144
+ .css("position", "absolute")
145
+ .css("margin", 0)
146
+ .css("padding", padding)
147
+ .css("background-color", bgcolor)
148
+ .css("color", textcolor);
149
+
150
+
151
+ // regist dialog move behavor.
152
+ dlg.mousedown(function(e){
153
+ dlg
154
+ .data("clickPointX" , e.pageX - dlg.offset().left)
155
+ .data("clickPointY" , e.pageY - dlg.offset().top);
156
+
157
+ $(document).mousemove(function(e){
158
+ dlg.css({
159
+ top :e.pageY - dlg.data("clickPointY")+"px",
160
+ left:e.pageX - dlg.data("clickPointX")+"px"
161
+ })
162
+ })
163
+ }).mouseup(function(){
164
+ $(document).unbind("mousemove")
165
+ })
166
+
167
+ /**
168
+ * show dialog.
169
+ * @param<string> message.
170
+ * @param<integer> show interval.
171
+ */
172
+ this.show = function(msg, interval){
173
+ dlg
174
+ .css("left", left)
175
+ .css("top", top)
176
+ .css("width", width)
177
+ .css("height", height)
178
+ .css("font-size", size)
179
+ .fadeIn("fast");
180
+
181
+ dlg
182
+ .empty()
183
+ .append(msg);
184
+
185
+ if(arguments.length >= 2){
186
+ setTimeout(function(){dlg.fadeOut("fast")} , interval);
187
+ }
188
+ };
189
+
190
+ /**
191
+ * close dialog.
192
+ */
193
+ this.close = function(){
194
+ dlg.fadeOut("fast");
195
+ }
196
+ }
197
+
198
+