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/.gitignore +1 -0
- data/Gemfile.lock +13 -16
- data/Rakefile +8 -0
- data/emacs/README.md +69 -0
- data/emacs/ROADMAP.md +69 -0
- data/emacs/vimgolf.el +343 -0
- data/lib/vimgolf.rb +2 -1
- data/lib/vimgolf/challenge.rb +108 -0
- data/lib/vimgolf/cli.rb +43 -104
- data/lib/vimgolf/keylog.rb +144 -24
- data/lib/vimgolf/ui.rb +26 -10
- data/lib/vimgolf/version.rb +1 -1
- data/spec/challenge_spec.rb +31 -0
- data/spec/cli_spec.rb +1 -17
- data/spec/helper.rb +1 -1
- data/spec/keylog_spec.rb +4 -3
- data/vimgolf.gemspec +3 -2
- metadata +85 -89
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,33 +1,30 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
vimgolf (0.
|
4
|
+
vimgolf (0.4.0)
|
5
5
|
highline
|
6
|
-
json
|
7
6
|
thor (>= 0.14.6)
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: http://rubygems.org/
|
11
10
|
specs:
|
12
|
-
diff-lcs (1.1.
|
13
|
-
highline (1.6.
|
14
|
-
|
15
|
-
rspec (2.
|
16
|
-
rspec-core (~> 2.
|
17
|
-
rspec-expectations (~> 2.
|
18
|
-
rspec-mocks (~> 2.
|
19
|
-
rspec-core (2.
|
20
|
-
rspec-expectations (2.
|
21
|
-
diff-lcs (~> 1.1.
|
22
|
-
rspec-mocks (2.
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
highline (1.6.11)
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rspec (2.9.0)
|
15
|
+
rspec-core (~> 2.9.0)
|
16
|
+
rspec-expectations (~> 2.9.0)
|
17
|
+
rspec-mocks (~> 2.9.0)
|
18
|
+
rspec-core (2.9.0)
|
19
|
+
rspec-expectations (2.9.0)
|
20
|
+
diff-lcs (~> 1.1.3)
|
21
|
+
rspec-mocks (2.9.0)
|
23
22
|
thor (0.14.6)
|
24
23
|
|
25
24
|
PLATFORMS
|
26
25
|
ruby
|
27
26
|
|
28
27
|
DEPENDENCIES
|
29
|
-
|
30
|
-
json
|
28
|
+
rake
|
31
29
|
rspec
|
32
|
-
thor (>= 0.14.6)
|
33
30
|
vimgolf!
|
data/Rakefile
CHANGED
data/emacs/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# VimGolf Minor Mode Roadmap
|
2
|
+
|
3
|
+
## Features
|
4
|
+
|
5
|
+
1. Completing read of challenges by title rather than by challenge id
|
6
|
+
|
7
|
+
2. `M-x vimgolf-browse`: Dired/Ibuffer/Magit-like interface to VimGolf challenges.
|
8
|
+
|
9
|
+
Bindings:
|
10
|
+
|
11
|
+
- Bindings should mimic Dired/Ibuffer wherever possible. Magit is listed primarily because I want TAB to open up the long description of the challenge.
|
12
|
+
|
13
|
+
At least:
|
14
|
+
|
15
|
+
- n/p
|
16
|
+
- ENTER/o: launch `vimgolf` with the correct arg.
|
17
|
+
|
18
|
+
Interface Mockup:
|
19
|
+
|
20
|
+
VimGolf in Emacs! Compete on vimgolf with the One True Editor.
|
21
|
+
|
22
|
+
Sort entries based on date - Sort some entries in a Ledger-file based on date.
|
23
|
+
PHP Array Syntax -> MailChimp Merge Syntax - I recently needed to send an e-m...
|
24
|
+
Refactor to Helpers
|
25
|
+
This Rails partial is almost all template escapes. Put it into a helper,
|
26
|
+
and refactor each case to methods so we can build out the controls for
|
27
|
+
each. (I've converted to tabs - fighting with Vimgolf's default config
|
28
|
+
shouldn't be part of the challenge.)
|
29
|
+
|
30
|
+
Alphabetize the directory - Put the contacts and their information in alphabe...
|
31
|
+
PHP <--> Java class conversion Part 2 - Same class but reverse!
|
32
|
+
PHP <--> Java class conversion Part 1 - Convert this tiny php class to adequa...
|
33
|
+
Multiplication table. - Create a multiplication table.
|
34
|
+
Complete the hex array data (Part II) - Do not use external tools(e.g. tac, s...
|
35
|
+
Interweave two blocks of text - Suppose you've got data on a list of things f...
|
36
|
+
.
|
37
|
+
.
|
38
|
+
.
|
39
|
+
|
40
|
+
--------------------------------------------------------------------------------
|
41
|
+
|
42
|
+
Commentary:
|
43
|
+
|
44
|
+
- Tab has been pressed on the Refactor to Helpers line and thus it's been expanded.
|
45
|
+
|
46
|
+
- The challenges `formatted text to markdown` and `Line Zipper` have both been completed and thus are hidden. Could provide a customization setting that turns this off completely, as well as an `M-x vimgolf-show-all` function to toggle the hiding.
|
47
|
+
|
48
|
+
- Fill column has been set to 80
|
49
|
+
|
50
|
+
- It would be fun if a local cache of the vimgolf data could be kept together so that you could record solutions or at least play offline.
|
51
|
+
|
52
|
+
3. Real submission to vimgolf.
|
53
|
+
|
54
|
+
This could look like:
|
55
|
+
|
56
|
+
Pop-open buffer
|
57
|
+
|
58
|
+
You solved the formatted text to markdown challenge in 25 keystrokes! The best entry for this challenge was 23.
|
59
|
+
|
60
|
+
M-x qrr ;; query-replace-regexp
|
61
|
+
SPC*2 ;; self-insert-command
|
62
|
+
dummy ;; self-insert-command * 5
|
63
|
+
.
|
64
|
+
.
|
65
|
+
.
|
66
|
+
|
67
|
+
Mini-buffer
|
68
|
+
|
69
|
+
Submit to your solution to vimgolf? <y-or-n-predicate>
|
data/emacs/ROADMAP.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# VimGolf Minor Mode Roadmap
|
2
|
+
|
3
|
+
## Features
|
4
|
+
|
5
|
+
1. Completing read of challenges by title rather than by challenge id
|
6
|
+
|
7
|
+
2. `M-x vimgolf-browse`: Dired/Ibuffer/Magit-like interface to VimGolf challenges.
|
8
|
+
|
9
|
+
Bindings:
|
10
|
+
|
11
|
+
- Bindings should mimic Dired/Ibuffer wherever possible. Magit is listed primarily because I want TAB to open up the long description of the challenge.
|
12
|
+
|
13
|
+
At least:
|
14
|
+
|
15
|
+
- n/p
|
16
|
+
- ENTER/o: launch `vimgolf` with the correct arg.
|
17
|
+
|
18
|
+
Interface Mockup:
|
19
|
+
|
20
|
+
VimGolf in Emacs! Compete on vimgolf with the One True Editor.
|
21
|
+
|
22
|
+
Sort entries based on date - Sort some entries in a Ledger-file based on date.
|
23
|
+
PHP Array Syntax -> MailChimp Merge Syntax - I recently needed to send an e-m...
|
24
|
+
Refactor to Helpers
|
25
|
+
This Rails partial is almost all template escapes. Put it into a helper,
|
26
|
+
and refactor each case to methods so we can build out the controls for
|
27
|
+
each. (I've converted to tabs - fighting with Vimgolf's default config
|
28
|
+
shouldn't be part of the challenge.)
|
29
|
+
|
30
|
+
Alphabetize the directory - Put the contacts and their information in alphabe...
|
31
|
+
PHP <--> Java class conversion Part 2 - Same class but reverse!
|
32
|
+
PHP <--> Java class conversion Part 1 - Convert this tiny php class to adequa...
|
33
|
+
Multiplication table. - Create a multiplication table.
|
34
|
+
Complete the hex array data (Part II) - Do not use external tools(e.g. tac, s...
|
35
|
+
Interweave two blocks of text - Suppose you've got data on a list of things f...
|
36
|
+
.
|
37
|
+
.
|
38
|
+
.
|
39
|
+
|
40
|
+
--------------------------------------------------------------------------------
|
41
|
+
|
42
|
+
Commentary:
|
43
|
+
|
44
|
+
- Tab has been pressed on the Refactor to Helpers line and thus it's been expanded.
|
45
|
+
|
46
|
+
- The challenges `formatted text to markdown` and `Line Zipper` have both been completed and thus are hidden. Could provide a customization setting that turns this off completely, as well as an `M-x vimgolf-show-all` function to toggle the hiding.
|
47
|
+
|
48
|
+
- Fill column has been set to 80
|
49
|
+
|
50
|
+
- It would be fun if a local cache of the vimgolf data could be kept together so that you could record solutions or at least play offline.
|
51
|
+
|
52
|
+
3. Real submission to vimgolf.
|
53
|
+
|
54
|
+
This could look like:
|
55
|
+
|
56
|
+
Pop-open buffer
|
57
|
+
|
58
|
+
You solved the formatted text to markdown challenge in 25 keystrokes! The best entry for this challenge was 23.
|
59
|
+
|
60
|
+
M-x qrr ;; query-replace-regexp
|
61
|
+
SPC*2 ;; self-insert-command
|
62
|
+
dummy ;; self-insert-command * 5
|
63
|
+
.
|
64
|
+
.
|
65
|
+
.
|
66
|
+
|
67
|
+
Mini-buffer
|
68
|
+
|
69
|
+
Submit to your solution to vimgolf? <y-or-n-predicate>
|
data/emacs/vimgolf.el
ADDED
@@ -0,0 +1,343 @@
|
|
1
|
+
;;; vimgolf.el --- VimGolf interface for the One True Editor
|
2
|
+
|
3
|
+
;; Copyright (C) never, by no one
|
4
|
+
|
5
|
+
;;; Author: Tim Visher <tim.visher@gmail.com>
|
6
|
+
;;; Maintainer: Tim Visher <tim.visher@gmail.com>
|
7
|
+
;;; Created: 2011-11-02
|
8
|
+
;;; Version: 0.9.2
|
9
|
+
;;; Keywords: games vimgolf vim
|
10
|
+
|
11
|
+
;; This file is not part of GNU Emacs
|
12
|
+
|
13
|
+
;;; Commentary:
|
14
|
+
|
15
|
+
;; This is a simple package that allows Emacs users to compete on [VimGolf][1]
|
16
|
+
;; using the One True Editor. Competition can be commenced utilizing `M-x
|
17
|
+
;; vimgolf`. When finished with a challenge, `C-c C-v C-c` should finish your
|
18
|
+
;; editing, ensure correctness, and submit your score and keystrokes to
|
19
|
+
;; [VimGolf][1].
|
20
|
+
;;
|
21
|
+
;; On second thought, let's not go to Camelot. It's a silly place.
|
22
|
+
;;
|
23
|
+
;; Patches are accepted at https://github.com/timvisher/vimgolf
|
24
|
+
;;
|
25
|
+
;; [1]: http://vimgolf.com/
|
26
|
+
|
27
|
+
;;; Installation:
|
28
|
+
|
29
|
+
;; Use package.el. You'll need to add Marmalade to your archives:
|
30
|
+
|
31
|
+
;; (require 'package)
|
32
|
+
;; (add-to-list 'package-archives
|
33
|
+
;; '("marmalade" . "http://marmalade-repo.org/packages/"))
|
34
|
+
|
35
|
+
;; If you use a version of Emacs prior to 24 that doesn't include
|
36
|
+
;; package.el, you can get it from http://bit.ly/pkg-el23. If you have
|
37
|
+
;; an older package.el installed from tromey.com, you should upgrade
|
38
|
+
;; in order to support installation from multiple sources.
|
39
|
+
|
40
|
+
;;; License:
|
41
|
+
|
42
|
+
;; [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/)
|
43
|
+
|
44
|
+
;;; Contributors
|
45
|
+
|
46
|
+
;; Tim Visher (@timvisher)
|
47
|
+
;; Steve Purcell (@sanityinc)
|
48
|
+
;; Adam Collard (@acollard)
|
49
|
+
|
50
|
+
;;; Code:
|
51
|
+
|
52
|
+
(defgroup vimgolf nil
|
53
|
+
"Compete on VimGolf with the One True Editor."
|
54
|
+
:prefix "vimgolf-"
|
55
|
+
:group 'applications)
|
56
|
+
|
57
|
+
(defcustom vimgolf-key nil
|
58
|
+
"Your VimGolf API Key. Must be set in order to submit your solution."
|
59
|
+
:type 'string
|
60
|
+
:group 'vimgolf)
|
61
|
+
|
62
|
+
(defcustom vimgolf-mode-hook '((lambda () (whitespace-mode t)))
|
63
|
+
"A list of functions to call upon the initialization of vimgolf-mode."
|
64
|
+
:type 'hook
|
65
|
+
:group 'vimgolf)
|
66
|
+
|
67
|
+
(defvar vimgolf-mode-map
|
68
|
+
(let ((map (make-sparse-keymap)))
|
69
|
+
(define-key map (kbd "C-c C-v C-c") 'vimgolf-submit)
|
70
|
+
(define-key map (kbd "C-c C-v r") 'vimgolf-revert)
|
71
|
+
(define-key map (kbd "C-c C-v d") 'vimgolf-diff)
|
72
|
+
(define-key map (kbd "C-c C-v c") 'vimgolf-continue)
|
73
|
+
(define-key map (kbd "C-c C-v p") 'vimgolf-pause)
|
74
|
+
(define-key map (kbd "C-c C-v q") 'vimgolf-quit)
|
75
|
+
map))
|
76
|
+
|
77
|
+
(define-minor-mode vimgolf-mode
|
78
|
+
"Toggle VimGolf mode.
|
79
|
+
|
80
|
+
With no argument, this command toggles the mode. Non-null prefix
|
81
|
+
argument turns on the mode. Null prefix argument turns off the
|
82
|
+
mode.
|
83
|
+
|
84
|
+
When VimGolf mode is enabled, several key bindings are defined
|
85
|
+
with `C-c C-v` prefixes to help in playing VimGolf.
|
86
|
+
|
87
|
+
\\{vimgolf-mode-map}"
|
88
|
+
;; The initial value.
|
89
|
+
nil
|
90
|
+
;; The indicator for the mode line.
|
91
|
+
" VimGolf"
|
92
|
+
;; The minor mode bindings.
|
93
|
+
:keymap vimgolf-mode-map
|
94
|
+
:group 'vimgolf)
|
95
|
+
|
96
|
+
(defvar vimgolf-challenge nil)
|
97
|
+
(defvar vimgolf-challenge-history nil)
|
98
|
+
|
99
|
+
(defvar vimgolf-prior-window-configuration nil)
|
100
|
+
|
101
|
+
(defvar vimgolf-working-window-configuration nil)
|
102
|
+
|
103
|
+
(defvar vimgolf-work-buffer-name "*vimgolf-work*")
|
104
|
+
(defvar vimgolf-start-buffer-name "*vimgolf-start*")
|
105
|
+
(defvar vimgolf-end-buffer-name "*vimgolf-end*")
|
106
|
+
(defvar vimgolf-keystrokes-buffer-name "*vimgolf-keystrokes*")
|
107
|
+
|
108
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
109
|
+
;; Keystroke logging
|
110
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
111
|
+
|
112
|
+
(defmacro vimgolf-with-saved-command-environment (&rest body)
|
113
|
+
`(let ((deactivate-mark nil)
|
114
|
+
(this-command this-command)
|
115
|
+
(last-command last-command))
|
116
|
+
,@body))
|
117
|
+
|
118
|
+
(defun vimgolf-capturable-keystroke-p ()
|
119
|
+
(not (or executing-kbd-macro
|
120
|
+
(member this-command
|
121
|
+
'(digit-argument
|
122
|
+
negative-argument
|
123
|
+
universal-argument
|
124
|
+
universal-argument-other-key
|
125
|
+
universal-argument-minus
|
126
|
+
universal-argument-more))
|
127
|
+
(string-prefix-p "vimgolf-" (symbol-name this-command)))))
|
128
|
+
|
129
|
+
(defun vimgolf-capturable-dangling-keystroke-p ()
|
130
|
+
(member this-command
|
131
|
+
'(calc-dispatch)))
|
132
|
+
|
133
|
+
(defvar vimgolf-keystrokes nil
|
134
|
+
"A list of (keys-vector . command) pairs for the keystrokes entered.
|
135
|
+
|
136
|
+
Each entry is a cons cell containing a key sequence vector
|
137
|
+
suitable for use with `key-description', and a symbol for the
|
138
|
+
command that was executed as a result (which may be nil if an
|
139
|
+
unknown key sequence was entered).")
|
140
|
+
|
141
|
+
(defun vimgolf-maybe-capture-keystroke (pred)
|
142
|
+
"Store the keystrokes for `this-command' if result of calling function `PRED' is not nil."
|
143
|
+
(vimgolf-with-saved-command-environment
|
144
|
+
(when (funcall pred)
|
145
|
+
(setq vimgolf-keystrokes
|
146
|
+
(append vimgolf-keystrokes (list (cons (this-command-keys-vector)
|
147
|
+
this-command)))))))
|
148
|
+
|
149
|
+
(defun vimgolf-capture-keystroke ()
|
150
|
+
(vimgolf-maybe-capture-keystroke 'vimgolf-capturable-keystroke-p))
|
151
|
+
|
152
|
+
(defun vimgolf-capture-dangling-keystroke ()
|
153
|
+
(vimgolf-maybe-capture-keystroke 'vimgolf-capturable-dangling-keystroke-p))
|
154
|
+
|
155
|
+
(defun vimgolf-refresh-keystroke-log ()
|
156
|
+
"Refresh the contents of the keystrokes log buffer."
|
157
|
+
(let ((deactivate-mark nil))
|
158
|
+
(with-current-buffer (get-buffer-create vimgolf-keystrokes-buffer-name)
|
159
|
+
(vimgolf-mode t)
|
160
|
+
(erase-buffer)
|
161
|
+
(insert (format "Challenge ID: %s\n%s\n\n" vimgolf-challenge (vimgolf-challenge-url vimgolf-challenge))
|
162
|
+
(format "Keystrokes (%d):\n\n" (vimgolf-count-keystrokes))
|
163
|
+
(mapconcat 'key-description (mapcar 'car vimgolf-keystrokes) " ")
|
164
|
+
"\n\nFull command log:\n\n")
|
165
|
+
(when vimgolf-keystrokes
|
166
|
+
(let* ((descrs-and-commands
|
167
|
+
(mapcar (lambda (entry) (cons (key-description (car entry)) (cdr entry))) vimgolf-keystrokes))
|
168
|
+
(maxlen (apply 'max (mapcar 'length (mapcar 'car descrs-and-commands))))
|
169
|
+
(fmt (format "%%-%ds %%s" maxlen)))
|
170
|
+
(dolist (entry descrs-and-commands)
|
171
|
+
(insert (format fmt (car entry) (prin1-to-string (cdr entry) t)) "\n")))))))
|
172
|
+
|
173
|
+
(defun vimgolf-enable-capture (enable)
|
174
|
+
"Enable keystroke logging if `ENABLE' is non-nil otherwise disable it."
|
175
|
+
(let ((f (if enable 'add-hook 'remove-hook)))
|
176
|
+
(funcall f 'pre-command-hook 'vimgolf-capture-keystroke)
|
177
|
+
(funcall f 'post-command-hook 'vimgolf-capture-dangling-keystroke)
|
178
|
+
(funcall f 'post-command-hook 'vimgolf-refresh-keystroke-log)))
|
179
|
+
|
180
|
+
(defun vimgolf-count-keystrokes ()
|
181
|
+
(apply '+ (mapcar 'length (mapcar 'car vimgolf-keystrokes))))
|
182
|
+
|
183
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
184
|
+
;; Managing and scoring challenges
|
185
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
186
|
+
|
187
|
+
(defun vimgolf-solution-correct-p ()
|
188
|
+
"Return t if the work text is identical to the solution, nil otherwise."
|
189
|
+
(let ((working (with-current-buffer vimgolf-work-buffer-name (buffer-string)))
|
190
|
+
(end (with-current-buffer vimgolf-end-buffer-name (buffer-string))))
|
191
|
+
(string= working end)))
|
192
|
+
|
193
|
+
(defun vimgolf-wrong-solution ()
|
194
|
+
(message "Wrong!")
|
195
|
+
(vimgolf-diff))
|
196
|
+
|
197
|
+
(defun vimgolf-right-solution ()
|
198
|
+
(delete-other-windows)
|
199
|
+
(switch-to-buffer vimgolf-keystrokes-buffer-name)
|
200
|
+
(message "Hurray! You solved %s in %d keystrokes!" vimgolf-challenge (vimgolf-count-keystrokes)))
|
201
|
+
|
202
|
+
(defun vimgolf-submit ()
|
203
|
+
"Stop the challenge and attempt to submit the solution to VimGolf."
|
204
|
+
(interactive)
|
205
|
+
(vimgolf-enable-capture nil)
|
206
|
+
(if (vimgolf-solution-correct-p) (vimgolf-right-solution) (vimgolf-wrong-solution)))
|
207
|
+
|
208
|
+
(defun vimgolf-clear-keystrokes ()
|
209
|
+
(setq vimgolf-keystrokes nil))
|
210
|
+
|
211
|
+
(defun vimgolf-reset-work-buffer ()
|
212
|
+
"Reset the contents of the work buffer, and clear undo/macro history etc."
|
213
|
+
(with-current-buffer (get-buffer-create vimgolf-work-buffer-name)
|
214
|
+
(vimgolf-init-buffer (current-buffer)
|
215
|
+
(with-current-buffer vimgolf-start-buffer-name
|
216
|
+
(buffer-string)))
|
217
|
+
(when defining-kbd-macro
|
218
|
+
(end-kbd-macro))
|
219
|
+
(vimgolf-clear-keystrokes)
|
220
|
+
(setq buffer-undo-list nil)
|
221
|
+
(set-buffer-modified-p nil)))
|
222
|
+
|
223
|
+
(defun vimgolf-revert ()
|
224
|
+
"Revert the work buffer to it's original state and reset keystrokes."
|
225
|
+
(interactive)
|
226
|
+
(vimgolf-reset-work-buffer)
|
227
|
+
(set-window-configuration vimgolf-working-window-configuration)
|
228
|
+
(message "If at first you don't succeed, try, try again."))
|
229
|
+
|
230
|
+
(defun vimgolf-diff ()
|
231
|
+
"Pause the competition and view differences between the buffers."
|
232
|
+
(interactive)
|
233
|
+
(vimgolf-enable-capture nil)
|
234
|
+
(ediff-buffers (get-buffer-create vimgolf-work-buffer-name) (get-buffer-create vimgolf-end-buffer-name))
|
235
|
+
(message "Remember to `C-c C-v c` when you're done."))
|
236
|
+
|
237
|
+
(defun vimgolf-continue ()
|
238
|
+
"Restore work and end buffers and begin recording keystrokes again."
|
239
|
+
(interactive)
|
240
|
+
(vimgolf-enable-capture t)
|
241
|
+
(set-window-configuration vimgolf-working-window-configuration)
|
242
|
+
(message "Golf away!"))
|
243
|
+
|
244
|
+
(defun vimgolf-pause ()
|
245
|
+
"Stop recording keystrokes."
|
246
|
+
(interactive)
|
247
|
+
(vimgolf-enable-capture nil)
|
248
|
+
(message "Come `C-c C-v c` soon."))
|
249
|
+
|
250
|
+
(defun vimgolf-quit ()
|
251
|
+
"Cancel the competition."
|
252
|
+
(interactive)
|
253
|
+
(vimgolf-enable-capture nil)
|
254
|
+
(vimgolf-kill-existing-session)
|
255
|
+
(set-window-configuration vimgolf-prior-window-configuration)
|
256
|
+
(message "I declare you, n00b!"))
|
257
|
+
|
258
|
+
(defvar vimgolf-host "http://vimgolf.com/")
|
259
|
+
|
260
|
+
;; (setq vimgolf-host "http://vimgolf.local:8888/")
|
261
|
+
;; (setq vimgolf-host "http://vimgolf.com/")
|
262
|
+
;; Overall VimGolf Rank ID: 4d2fb20e63b08b08b0000075
|
263
|
+
;; Sort entries based on date ID: 4ea9bc988b36f70001000008
|
264
|
+
;; HTML to Haml ID: 4d3c51f1aabf526ed6000030
|
265
|
+
;; Assignment Allignment: 4d2c9d06eda6262e4e00007a
|
266
|
+
|
267
|
+
(defvar vimgolf-challenge-extension ".yaml")
|
268
|
+
|
269
|
+
(defun vimgolf-challenge-path (challenge-id)
|
270
|
+
(concat "challenges/" challenge-id))
|
271
|
+
|
272
|
+
(defun vimgolf-challenge-url (challenge-id)
|
273
|
+
(concat vimgolf-host (vimgolf-challenge-path challenge-id) vimgolf-challenge-extension))
|
274
|
+
|
275
|
+
(defun vimgolf-init-buffer (buffer text)
|
276
|
+
(with-current-buffer buffer
|
277
|
+
(erase-buffer)
|
278
|
+
(insert text)
|
279
|
+
(goto-char (point-min))
|
280
|
+
(vimgolf-mode t)))
|
281
|
+
|
282
|
+
(defun vimgolf-kill-existing-session ()
|
283
|
+
"Kill any vimgolf-related buffers."
|
284
|
+
(dolist (buf (list vimgolf-start-buffer-name
|
285
|
+
vimgolf-work-buffer-name
|
286
|
+
vimgolf-end-buffer-name
|
287
|
+
vimgolf-keystrokes-buffer-name))
|
288
|
+
(when (get-buffer buf)
|
289
|
+
(kill-buffer buf))))
|
290
|
+
|
291
|
+
(defun vimgolf-read-next-data-chunk ()
|
292
|
+
"Return the next chunk of data as a string, leaving the point at the end of that chunk."
|
293
|
+
(let ((data-start-regexp " data: |\\+\\{0,1\\}\n")
|
294
|
+
(data-end-regexp "\\([ ]\\{4\\}\\|[ ]\\{0\\}\\)\n type: [-a-z]+"))
|
295
|
+
(unless (re-search-forward data-start-regexp nil t)
|
296
|
+
(error "Can't find data in response from vimgolf"))
|
297
|
+
(let ((start (point)))
|
298
|
+
(unless (re-search-forward data-end-regexp nil t)
|
299
|
+
(error "Unclosed data section in response from vimgolf"))
|
300
|
+
(let ((str (buffer-substring-no-properties start (match-beginning 0))))
|
301
|
+
(replace-regexp-in-string "^ " "" str)))))
|
302
|
+
|
303
|
+
(defun vimgolf-setup (status challenge-id)
|
304
|
+
(vimgolf-clear-keystrokes)
|
305
|
+
(setq vimgolf-prior-window-configuration (current-window-configuration)
|
306
|
+
vimgolf-challenge challenge-id)
|
307
|
+
(goto-char (point-min))
|
308
|
+
(let* ((start-text (vimgolf-read-next-data-chunk))
|
309
|
+
(end-text (vimgolf-read-next-data-chunk)))
|
310
|
+
|
311
|
+
(vimgolf-kill-existing-session)
|
312
|
+
|
313
|
+
(let ((vimgolf-start-buffer (get-buffer-create vimgolf-start-buffer-name))
|
314
|
+
(vimgolf-work-buffer (get-buffer-create vimgolf-work-buffer-name))
|
315
|
+
(vimgolf-end-buffer (get-buffer-create vimgolf-end-buffer-name)))
|
316
|
+
|
317
|
+
(vimgolf-init-buffer vimgolf-start-buffer start-text)
|
318
|
+
(vimgolf-init-buffer vimgolf-end-buffer end-text)
|
319
|
+
(with-current-buffer vimgolf-end-buffer (setq buffer-read-only t))
|
320
|
+
(vimgolf-reset-work-buffer)
|
321
|
+
|
322
|
+
;; Set up windows
|
323
|
+
(delete-other-windows)
|
324
|
+
(display-buffer vimgolf-end-buffer 'display-buffer-pop-up-window)
|
325
|
+
(set-window-buffer (selected-window) vimgolf-work-buffer)
|
326
|
+
(switch-to-buffer vimgolf-work-buffer)
|
327
|
+
(setq vimgolf-working-window-configuration (current-window-configuration))
|
328
|
+
|
329
|
+
(vimgolf-continue))))
|
330
|
+
|
331
|
+
;;;###autoload
|
332
|
+
(defun vimgolf (challenge-id)
|
333
|
+
"Open a VimGolf Challenge"
|
334
|
+
(interactive (list (read-from-minibuffer "Challenge ID: " nil nil nil 'vimgolf-challenge-history)))
|
335
|
+
(url-retrieve (vimgolf-challenge-url challenge-id) 'vimgolf-setup `(,challenge-id)))
|
336
|
+
|
337
|
+
(provide 'vimgolf)
|
338
|
+
|
339
|
+
;;; Local Variables:
|
340
|
+
;;; tab-width:2
|
341
|
+
;;; indent-tabs-mode:nil
|
342
|
+
;;; End:
|
343
|
+
;;; vimgolf.el ends here
|