vimgolf 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/vimgolf.rb CHANGED
@@ -7,5 +7,6 @@ require 'thor'
7
7
  require 'vimgolf/version'
8
8
  require 'vimgolf/config'
9
9
  require 'vimgolf/keylog'
10
+ require 'vimgolf/challenge'
10
11
  require 'vimgolf/cli'
11
- require 'vimgolf/ui'
12
+ require 'vimgolf/ui'
@@ -0,0 +1,108 @@
1
+ module VimGolf
2
+ class Challenge
3
+ attr_reader :id, :type
4
+
5
+ def self.path(path)
6
+ @@path = path if path
7
+ @@path
8
+ end
9
+
10
+ def initialize(id)
11
+ @id = id
12
+ end
13
+
14
+ def download
15
+ begin
16
+ url = URI.parse("#{GOLFHOST}/challenges/#{@id}.yaml")
17
+ req = Net::HTTP::Get.new(url.path)
18
+
19
+ proxy_url, proxy_user, proxy_pass = get_proxy
20
+ proxy = Net::HTTP::Proxy(proxy_url.host, proxy_url.port, proxy_user, proxy_pass)
21
+ res = proxy.start(url.host, url.port) { |http| http.request(req) }
22
+
23
+ @data = YAML.load(res.body)
24
+
25
+ if !@data.is_a? Hash
26
+ raise
27
+
28
+ elsif @data['client'] != Vimgolf::VERSION
29
+ VimGolf.ui.error "Client version mismatch. Installed: #{Vimgolf::VERSION}, Required: #{@data['client']}."
30
+ VimGolf.ui.error "\t gem install vimgolf"
31
+ raise "Bad Version"
32
+ end
33
+
34
+ @type = @data['in']['type']
35
+ save
36
+ start
37
+ rescue Exception => e
38
+ debug(e)
39
+ raise "Uh oh, couldn't download or parse challenge, please verify your challenge id & client version."
40
+ end
41
+ end
42
+
43
+ def start
44
+ File.open(work_path, "w") {|f| f.puts @data['in']['data']}
45
+ end
46
+
47
+ def save
48
+ File.open(input_path, "w") {|f| f.puts @data['in']['data']}
49
+ File.open(output_path, "w") {|f| f.puts @data['out']['data']}
50
+ File.open(vimrc_path, "w") {|f| f.puts @data['vimrc']}
51
+ end
52
+
53
+ def upload
54
+ begin
55
+ url = URI.parse("#{GOLFHOST}/entry.yaml")
56
+
57
+ proxy_url, proxy_user, proxy_pass = get_proxy
58
+ proxy = Net::HTTP::Proxy(proxy_url.host, proxy_url.port, proxy_user, proxy_pass)
59
+
60
+ proxy.start(url.host, url.port) do |http|
61
+ request = Net::HTTP::Post.new(url.request_uri)
62
+ request.set_form_data({"challenge_id" => @id, "apikey" => Config.load['key'], "entry" => IO.read(log_path)})
63
+ request["Accept"] = "text/yaml"
64
+
65
+ res = http.request(request)
66
+ res = YAML.load(res.body)
67
+
68
+ raise if !res.is_a? Hash
69
+ res['status'].to_sym
70
+
71
+ end
72
+ rescue Exception => e
73
+ debug(e)
74
+ raise "Uh oh, entry upload has failed, please check your key."
75
+ end
76
+ end
77
+
78
+ def input_path; path + ".#{@type}"; end
79
+ def work_path; path + ".work.#{@type}"; end
80
+ def output_path; path + ".output"; end
81
+ def log_path; path + ".log"; end
82
+ def vimrc_path; path + ".golfrc"; end
83
+
84
+ def path
85
+ @@path + "/#{@id}"
86
+ end
87
+
88
+ private
89
+ def get_proxy
90
+ begin
91
+ proxy_url = URI.parse(PROXY)
92
+ rescue Exception => e
93
+ VimGolf.ui.error "Invalid proxy uri in http_proxy environment variable - will try to run with out proxy"
94
+ proxy_url = URI.parse("");
95
+ end
96
+
97
+ proxy_url.port ||= 80
98
+ proxy_user, proxy_pass = proxy_url.userinfo.split(/:/) if proxy_url.userinfo
99
+
100
+ return proxy_url, proxy_user, proxy_pass
101
+ end
102
+
103
+ def debug(msg)
104
+ p [caller.first, msg] if GOLFDEBUG
105
+ end
106
+
107
+ end
108
+ end
data/lib/vimgolf/cli.rb CHANGED
@@ -1,14 +1,17 @@
1
1
  module VimGolf
2
2
 
3
- GOLFHOST = ENV['GOLFHOST'] || "http://vimgolf.com"
4
- GOLFDEBUG = ENV['GOLFDEBUG'].to_sym rescue false
5
- GOLFDIFF = ENV['GOFLDIFF'] || 'diff'
6
- GOLFVIM = ENV['GOLFVIM'] || 'vim'
7
- PROXY = ENV['http_proxy'] || ''
3
+ GOLFDEBUG = ENV['GOLFDEBUG'].to_sym rescue false
4
+ GOLFHOST = ENV['GOLFHOST'] || "http://vimgolf.com"
5
+ GOLFDIFF = ENV['GOLFDIFF'] || 'diff'
6
+ GOLFSHOWDIFF = ENV['GOLFSHOWDIFF'] || 'vim -d -n'
7
+ GOLFVIM = ENV['GOLFVIM'] || 'vim'
8
+ PROXY = ENV['http_proxy'] || ''
8
9
 
9
10
  class Error
10
11
  end
11
12
 
13
+ class RetryException < Exception; end
14
+
12
15
  class UI
13
16
  def debug(*); end
14
17
  end
@@ -60,39 +63,53 @@ module VimGolf
60
63
  DESC
61
64
 
62
65
  def put(id = nil)
63
- VimGolf.ui.warn "Launching VimGolf session for challenge: #{id}"
66
+ VimGolf.ui.warn "Downloading Vimgolf challenge: #{id}"
67
+ VimGolf::Challenge.path(Config.put_path)
68
+ challenge = Challenge.new(id)
69
+ challenge.download
64
70
 
65
71
  begin
66
- type = download(id)
67
-
72
+ VimGolf.ui.warn "Launching VimGolf session for challenge: #{id}"
68
73
  # - n - no swap file, memory only editing
69
74
  # - +0 - always start on line 0
70
75
  # - --noplugin - don't load any plugins, lets be fair!
71
76
  # -i NONE - don't load .viminfo (for saved macros and the like)
72
77
  # - u - load vimgolf .vimrc to level the playing field
73
- vimcmd = "#{GOLFVIM} -n --noplugin -i NONE +0 -u \"#{vimrc(id)}\" -W \"#{log(id)}\" \"#{input(id, type)}\""
78
+ vimcmd = "#{GOLFVIM} -Z -n --noplugin -i NONE +0 -u \"#{vimrc(id)}\" -W \"#{log(id)}\" \"#{input(id, type)}\""
74
79
  debug(vimcmd)
75
80
  system(vimcmd)
76
81
 
77
82
  if $?.exitstatus.zero?
78
- diff = `#{GOLFDIFF} \"#{input(id, type)}\" \"#{output(id)}\"`
79
- score = Keylog.score(IO.read(log(id)))
83
+ diff_files = "\"#{challenge.work_path}\" \"#{challenge.output_path}\""
84
+ diff = `#{GOLFDIFF} #{diff_files}`
85
+ log = Keylog.new(IO.read(challenge.log_path))
80
86
 
81
87
  if diff.size > 0
82
- VimGolf.ui.warn "Uh oh, looks like your entry does not match the desired output:"
83
- VimGolf.ui.warn "#"*50
84
- puts diff
85
- VimGolf.ui.warn "#"*50
86
- VimGolf.ui.warn "Please try again! Your score for this (failed) attempt was: #{score}"
87
- return
88
+ VimGolf.ui.warn "Uh oh, looks like your entry does not match the desired output."
89
+ loop do
90
+ case VimGolf.ui.ask_question "Would you like to see a [d]iff or [r]etry or [q]uit ?",
91
+ :type => :warn,
92
+ :choices => [:diff, :retry, :quit]
93
+ when :diff
94
+ VimGolf.ui.warn "Showing vimdiff of your attempt (left) and correct output (right)"
95
+ system("#{GOLFSHOWDIFF} #{diff_files}")
96
+ when :retry
97
+ VimGolf.ui.warn "Your score for this (failed) attempt was: #{log.score}. Let's try again!!\n#{'#'*50}"
98
+ challenge.start
99
+ raise RetryException
100
+ when :quit
101
+ VimGolf.ui.warn "Please try again! Your score for this (failed) attempt was: #{log.score}"
102
+ return
103
+ end
104
+ end
88
105
  end
89
106
 
90
- VimGolf.ui.info "Success! Your output matches. Your score: #{score}"
107
+ VimGolf.ui.info "Success! Your output matches. Your score: #{log.score}"
91
108
 
92
109
  if VimGolf.ui.yes? "Upload result to VimGolf? (yes / no)"
93
110
  VimGolf.ui.warn "Uploading to VimGolf..."
94
111
 
95
- if upload(id) == :ok
112
+ if challenge.upload == :ok
96
113
  VimGolf.ui.info "Uploaded entry, thanks for golfing!"
97
114
  VimGolf.ui.info "View the leaderboard: #{GOLFHOST}/challenges/#{id}"
98
115
  else
@@ -112,97 +129,19 @@ module VimGolf
112
129
  VimGolf.ui.error error
113
130
  end
114
131
 
115
- rescue Exception => e
116
- VimGolf.ui.error "Uh oh, something went wrong! Error: #{e}"
117
- VimGolf.ui.error "If the error persists, please report it to github.com/igrigorik/vimgolf"
118
- end
119
- end
120
-
121
- no_tasks do
122
- def download(id)
123
- begin
124
- url = URI.parse("#{GOLFHOST}/challenges/#{id}.yaml")
125
- req = Net::HTTP::Get.new(url.path)
126
-
127
- proxy_url, proxy_user, proxy_pass = get_proxy
128
- proxy = Net::HTTP::Proxy(proxy_url.host, proxy_url.port, proxy_user, proxy_pass)
129
- res = proxy.start(url.host, url.port) { |http| http.request(req) }
130
-
131
- data = YAML.load(res.body)
132
-
133
- if !data.is_a? Hash
134
- raise
135
-
136
- elsif data['client'] != Vimgolf::VERSION
137
- VimGolf.ui.error "Client version mismatch. Installed: #{Vimgolf::VERSION}, Required: #{data['client']}."
138
- VimGolf.ui.error "\t gem install vimgolf"
139
- raise "Bad Version"
140
- end
141
-
142
- File.open(Config.put_path + "/#{id}.#{data['in']['type']}", "w") {|f| f.puts data['in']['data']}
143
- File.open(Config.put_path + "/#{id}.output", "w") {|f| f.puts data['out']['data']}
144
- File.open(Config.put_path + "/#{id}.golfrc", "w") {|f| f.puts data['vimrc']}
145
-
146
- data['in']['type']
147
-
148
- rescue Exception => e
149
- debug(e)
150
- raise "Uh oh, couldn't download or parse challenge, please verify your challenge id & client version."
151
- end
132
+ rescue RetryException => e
133
+ retry
152
134
  end
153
135
 
154
- def upload(id)
155
- begin
156
- url = URI.parse("#{GOLFHOST}/entry.yaml")
157
-
158
- proxy_url, proxy_user, proxy_pass = get_proxy
159
- proxy = Net::HTTP::Proxy(proxy_url.host, proxy_url.port, proxy_user, proxy_pass)
160
-
161
- proxy.start(url.host, url.port) do |http|
162
- request = Net::HTTP::Post.new(url.request_uri)
163
- request.set_form_data({"challenge_id" => id, "apikey" => Config.load['key'], "entry" => IO.read(log(id))})
164
- request["Accept"] = "text/yaml"
165
-
166
- res = http.request(request)
167
- res = YAML.load(res.body)
168
-
169
- raise if !res.is_a? Hash
170
- res['status'].to_sym
171
-
172
- end
173
- rescue Exception => e
174
- debug(e)
175
- raise "Uh oh, entry upload has failed, please check your key."
176
- end
177
- end
136
+ rescue Exception => e
137
+ VimGolf.ui.error "Uh oh, something went wrong! Error: #{e}"
138
+ VimGolf.ui.error "If the error persists, please report it to github.com/igrigorik/vimgolf"
178
139
  end
179
140
 
180
141
  private
181
- def input(id, type); challenge(id) + ".#{type}"; end
182
- def output(id); challenge(id) + ".output"; end
183
- def log(id); challenge(id) + ".log"; end
184
- def vimrc(id); challenge(id) + ".golfrc"; end
185
-
186
- def challenge(id)
187
- Config.put_path + "/#{id}"
188
- end
189
-
190
- def get_proxy
191
- begin
192
- proxy_url = URI.parse(PROXY)
193
- rescue Exception => e
194
- VimGolf.ui.error "Invalid proxy uri in http_proxy environment variable - will try to run with out proxy"
195
- proxy_url = URI.parse("");
196
- end
197
-
198
- proxy_url.port ||= 80
199
- proxy_user, proxy_pass = proxy_url.userinfo.split(/:/) if proxy_url.userinfo
200
-
201
- return proxy_url, proxy_user, proxy_pass
202
- end
203
-
204
142
  def debug(msg)
205
143
  p [caller.first, msg] if GOLFDEBUG
206
144
  end
207
145
  end
208
- end
146
+
147
+ end
@@ -1,29 +1,20 @@
1
1
  module VimGolf
2
- class Session < Array
3
- def to_s(sep = '')
4
- @log.join(sep)
5
- end
6
- end
7
-
8
2
  class Keylog
9
- def self.parse(input)
10
- session = Session.new
11
- scan(input) {|s| session << s }
12
- session
13
- end
3
+ include Enumerable
4
+
5
+ alias_method :convert , :to_s
6
+ alias_method :score , :count
14
7
 
15
- def self.convert(input)
16
- parse(input).join('')
8
+ def initialize(input)
9
+ @input = input
17
10
  end
18
11
 
19
- def self.score(input)
20
- keys = 0
21
- scan(input) {|s| keys += 1 }
22
- keys
12
+ def to_s(sep = '')
13
+ to_a.join(sep)
23
14
  end
24
15
 
25
- def self.scan(input)
26
- scanner = StringScanner.new(input)
16
+ def each
17
+ scanner = StringScanner.new(@input)
27
18
  output = ""
28
19
 
29
20
  until scanner.eos?
@@ -37,9 +28,9 @@ module VimGolf
37
28
  when 0x80
38
29
  code = scanner.get_byte + scanner.get_byte
39
30
 
40
- # This list has been populated by experimentation so far,
41
- # because I haven't bothered looking for a more authoritative
42
- # source.
31
+ # This list has been populated by looking at
32
+ # :h terminal-options and vim source files:
33
+ # keymap.h and misc2.c
43
34
  case code
44
35
  when "k1"; "<F1>"
45
36
  when "k2"; "<F2>"
@@ -53,6 +44,38 @@ module VimGolf
53
44
  when "k;"; "<F10>"
54
45
  when "F1"; "<F11>"
55
46
  when "F2"; "<F12>"
47
+ when "F3"; "<F13>"
48
+ when "F4"; "<F14>"
49
+ when "F5"; "<F15>"
50
+ when "F6"; "<F16>"
51
+ when "F7"; "<F17>"
52
+ when "F8"; "<F18>"
53
+ when "F9"; "<F19>"
54
+
55
+ when "%1"; "<Help>"
56
+ when "&8"; "<Undo>"
57
+ when "#2"; "<S-Home>"
58
+ when "*7"; "<S-End>"
59
+ when "K1"; "<kHome>"
60
+ when "K4"; "<kEnd>"
61
+ when "K3"; "<kPageUp>"
62
+ when "K5"; "<kPageDown>"
63
+ when "K6"; "<kPlus>"
64
+ when "K7"; "<kMinus>"
65
+ when "K8"; "<kDivide>"
66
+ when "K9"; "<kMultiply>"
67
+ when "KA"; "<kEnter>"
68
+ when "KB"; "<kPoint>"
69
+ when "KC"; "<k0>"
70
+ when "KD"; "<k1>"
71
+ when "KE"; "<k2>"
72
+ when "KF"; "<k3>"
73
+ when "KG"; "<k4>"
74
+ when "KH"; "<k5>"
75
+ when "KI"; "<k6>"
76
+ when "KJ"; "<k7>"
77
+ when "KK"; "<k8>"
78
+ when "KL"; "<k9>"
56
79
 
57
80
  when "kP"; "<PageUp>"
58
81
  when "kN"; "<PageDown>"
@@ -70,7 +93,104 @@ module VimGolf
70
93
  when "%i"; "<S-Right>"
71
94
 
72
95
  when "kB"; "<S-Tab>"
73
- when "\xffX"; "<C-Space>"
96
+ when "\xffX"; "<C-@>"
97
+
98
+ when "\xfd\x4"; "<S-Up>"
99
+ when "\xfd\x5"; "<S-Down>"
100
+ when "\xfd\x6"; "<S-F1>"
101
+ when "\xfd\x7"; "<S-F2>"
102
+ when "\xfd\x8"; "<S-F3>"
103
+ when "\xfd\x9"; "<S-F4>"
104
+ when "\xfd\xa"; "<S-F5>"
105
+ when "\xfd\xb"; "<S-F6>"
106
+ when "\xfd\xc"; "<S-F7>"
107
+ when "\xfd\xd"; "<S-F9>"
108
+ when "\xfd\xe"; "<S-F10>"
109
+ when "\xfd\xf"; "<S-F10>"
110
+ when "\xfd\x10"; "<S-F11>"
111
+ when "\xfd\x11"; "<S-F12>"
112
+ when "\xfd\x12"; "<S-F13>"
113
+ when "\xfd\x13"; "<S-F14>"
114
+ when "\xfd\x14"; "<S-F15>"
115
+ when "\xfd\x15"; "<S-F16>"
116
+ when "\xfd\x16"; "<S-F17>"
117
+ when "\xfd\x17"; "<S-F18>"
118
+ when "\xfd\x18"; "<S-F19>"
119
+ when "\xfd\x19"; "<S-F20>"
120
+ when "\xfd\x1a"; "<S-F21>"
121
+ when "\xfd\x1b"; "<S-F22>"
122
+ when "\xfd\x1c"; "<S-F23>"
123
+ when "\xfd\x1d"; "<S-F24>"
124
+ when "\xfd\x1e"; "<S-F25>"
125
+ when "\xfd\x1f"; "<S-F26>"
126
+ when "\xfd\x20"; "<S-F27>"
127
+ when "\xfd\x21"; "<S-F28>"
128
+ when "\xfd\x22"; "<S-F29>"
129
+ when "\xfd\x23"; "<S-F30>"
130
+ when "\xfd\x24"; "<S-F31>"
131
+ when "\xfd\x25"; "<S-F32>"
132
+ when "\xfd\x26"; "<S-F33>"
133
+ when "\xfd\x27"; "<S-F34>"
134
+ when "\xfd\x28"; "<S-F35>"
135
+ when "\xfd\x29"; "<S-F36>"
136
+ when "\xfd\x2a"; "<S-F37>"
137
+ when "\xfd\x2b"; "<Mouse>"
138
+ when "\xfd\x2c"; "<LeftMouse>"
139
+ when "\xfd\x2d"; "<LeftDrag>"
140
+ when "\xfd\x2e"; "<LeftRelease>"
141
+ when "\xfd\x2f"; "<MiddleMouse>"
142
+ when "\xfd\x30"; "<MiddleDrag>"
143
+ when "\xfd\x31"; "<MiddleRelease>"
144
+ when "\xfd\x32"; "<RightMouse>"
145
+ when "\xfd\x33"; "<RightDrag>"
146
+ when "\xfd\x34"; "<RightRelease>"
147
+ #when "\xfd\x35"; "KE_IGNORE"
148
+ #when "\xfd\x36"; "KE_TAB"
149
+ #when "\xfd\x37"; "KE_S_TAB_OLD"
150
+ #when "\xfd\x38"; "KE_SNIFF"
151
+ #when "\xfd\x39"; "KE_XF1"
152
+ #when "\xfd\x3a"; "KE_XF2"
153
+ #when "\xfd\x3b"; "KE_XF3"
154
+ #when "\xfd\x3c"; "KE_XF4"
155
+ #when "\xfd\x3d"; "KE_XEND"
156
+ #when "\xfd\x3e"; "KE_ZEND"
157
+ #when "\xfd\x3f"; "KE_XHOME"
158
+ #when "\xfd\x40"; "KE_ZHOME"
159
+ #when "\xfd\x41"; "KE_XUP"
160
+ #when "\xfd\x42"; "KE_XDOWN"
161
+ #when "\xfd\x43"; "KE_XLEFT"
162
+ #when "\xfd\x44"; "KE_XRIGHT"
163
+ #when "\xfd\x45"; "KE_LEFTMOUSE_NM"
164
+ #when "\xfd\x46"; "KE_LEFTRELEASE_NM"
165
+ #when "\xfd\x47"; "KE_S_XF1"
166
+ #when "\xfd\x48"; "KE_S_XF2"
167
+ #when "\xfd\x49"; "KE_S_XF3"
168
+ #when "\xfd\x4a"; "KE_S_XF4"
169
+ when "\xfd\x4b"; "<MouseDown>"
170
+ when "\xfd\x4c"; "<MouseUp>"
171
+ when "\xfd\x4d"; "<MouseLeft>"
172
+ when "\xfd\x4e"; "<MouseRight>"
173
+ #when "\xfd\x4f"; "KE_KINS"
174
+ #when "\xfd\x50"; "KE_KDEL"
175
+ #when "\xfd\x51"; "KE_CSI"
176
+ #when "\xfd\x52"; "KE_SNR"
177
+ #when "\xfd\x53"; "KE_PLUG"
178
+ #when "\xfd\x54"; "KE_CMDWIN"
179
+ when "\xfd\x55"; "<C-Left>"
180
+ when "\xfd\x56"; "<C-Right>"
181
+ when "\xfd\x57"; "<C-Home>"
182
+ when "\xfd\x58"; "<C-End>"
183
+ #when "\xfd\x59"; "KE_X1MOUSE"
184
+ #when "\xfd\x5a"; "KE_X1DRAG"
185
+ #when "\xfd\x5b"; "KE_X1RELEASE"
186
+ #when "\xfd\x5c"; "KE_X2MOUSE"
187
+ #when "\xfd\x5d"; "KE_X2DRAG"
188
+ #when "\xfd\x5e"; "KE_X2RELEASE"
189
+ #when "\xfd\x5f"; "KE_DROP"
190
+ #when "\xfd\x5e"; "KE_CURSORHOLD"
191
+ #when "\xfd\x61"; "KE_NOP"
192
+ when "\xfd\x62"; nil # Focus Gained (GVIM)
193
+ when "\xfd\x63"; nil # Focus Lost (GVIM)
74
194
 
75
195
  else
76
196
  #puts "Unknown Vim code: #{code.inspect}"
@@ -98,7 +218,7 @@ module VimGolf
98
218
 
99
219
  end
100
220
 
101
- yield out_char
221
+ yield out_char if out_char
102
222
  end
103
223
  end
104
224
  end