vimgolf 0.4.8 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -10
- data/lib/vimgolf/challenge.rb +1 -1
- data/lib/vimgolf/cli.rb +14 -2
- data/lib/vimgolf/keylog.rb +242 -229
- data/lib/vimgolf/version.rb +1 -1
- metadata +51 -51
- data/.gitignore +0 -5
- data/.gitmodules +0 -3
- data/.rspec +0 -0
- data/Gemfile +0 -4
- data/Rakefile +0 -10
- data/emacs/CHANGELOG.md +0 -58
- data/emacs/README.md +0 -69
- data/emacs/ROADMAP.md +0 -69
- data/emacs/features/emacs.feature +0 -24
- data/emacs/features/step-definitions/emacs-steps.el +0 -53
- data/emacs/features/support/env.el +0 -37
- data/emacs/todo.org +0 -45
- data/emacs/vimgolf.el +0 -488
- data/spec/challenge_spec.rb +0 -31
- data/spec/cli_spec.rb +0 -25
- data/spec/fixtures/4d19832d8ae121365c00000b.log +0 -1
- data/spec/fixtures/4d1a1c36567bac34a9000002.log +0 -1
- data/spec/fixtures/4d1a1c69567bac34a9000004.log +0 -1
- data/spec/fixtures/4d1a21e88ae121365c00000e.log +0 -1
- data/spec/fixtures/4d1a34ccfa85f32065000004.log +0 -1
- data/spec/helper.rb +0 -25
- data/spec/keylog_spec.rb +0 -16
- data/vimgolf.gemspec +0 -42
@@ -1,53 +0,0 @@
|
|
1
|
-
;; This file contains your project specific step definitions. All
|
2
|
-
;; files in this directory whose names end with "-steps.el" will be
|
3
|
-
;; loaded automatically by Ecukes.
|
4
|
-
|
5
|
-
(Given "^I open the vimgolf browser$"
|
6
|
-
(lambda ()
|
7
|
-
(setq *vimgolf-browse-list*
|
8
|
-
'(("50128129201f450002000027"
|
9
|
-
"Complete the circuit grid!"
|
10
|
-
"Continuing from the last challenge, add additional rows to the grid. Change each of the names from 'A1'...'A10' to 'B1'...'B10', 'C1'...'C10', etc, and for each new row add 0.7 to the X values in the (X Y) at the end of each line. ")
|
11
|
-
("50127eba201f450002000024"
|
12
|
-
"Make the circuit grid!"
|
13
|
-
"Copy this command for a circuit layout program to create 10 total smd commands. Increment the number in quotes to name each pad, and add 0.7 to each of the (X Y) coordinates at the end of each line.")
|
14
|
-
("500855e60599d90002000073"
|
15
|
-
"Convert pandoc unordered list to a numbered list"
|
16
|
-
"I know it's possible to use #. in pandoc to auto-generate numbered lists, but then it's not easy to tell how many items there are when reading it in Markdown. How fast can you make the switch?")
|
17
|
-
("4fe62f8a8b2f800001000043"
|
18
|
-
"Cleanining up 80 column concatenated text"
|
19
|
-
"1. Put the whole query on one line, remove the concatenation operators
|
20
|
-
("4d1b4ac3c58eaa2a8a0005c2"
|
21
|
-
"Ruby 1.9 compat"
|
22
|
-
"Remember when Ruby supported `when <expr> :`? Well, it doesn't in 1.9, so let's make sure we use `then`, without ruining our lovely new hash syntax!")
|
23
|
-
))
|
24
|
-
(vimgolf-browse)))
|
25
|
-
|
26
|
-
(When "^I show the description$"
|
27
|
-
(lambda ()
|
28
|
-
(vimgolf-show-description)))
|
29
|
-
|
30
|
-
(Given "^I have \"\\(.+\\)\"$"
|
31
|
-
(lambda (something)
|
32
|
-
;; Do something
|
33
|
-
))
|
34
|
-
|
35
|
-
(When "^I have \"\\(.+\\)\"$"
|
36
|
-
(lambda (something)
|
37
|
-
;; Do something
|
38
|
-
))
|
39
|
-
|
40
|
-
(Then "^I should have \"\\(.+\\)\"$"
|
41
|
-
(lambda (something)
|
42
|
-
;; Do something
|
43
|
-
))
|
44
|
-
|
45
|
-
(And "^I have \"\\(.+\\)\"$"
|
46
|
-
(lambda (something)
|
47
|
-
;; Do something
|
48
|
-
))
|
49
|
-
|
50
|
-
(But "^I should not have \"\\(.+\\)\"$"
|
51
|
-
(lambda (something)
|
52
|
-
;; Do something
|
53
|
-
))
|
@@ -1,37 +0,0 @@
|
|
1
|
-
;; This is an example of how you could set up this file. This setup
|
2
|
-
;; requires a directory called util in the project root and that the
|
3
|
-
;; util directory contains the testing tools ert and espuds.
|
4
|
-
|
5
|
-
(let* ((features-directory
|
6
|
-
(file-name-directory
|
7
|
-
(directory-file-name (file-name-directory load-file-name))))
|
8
|
-
(project-directory
|
9
|
-
(file-name-directory
|
10
|
-
(directory-file-name features-directory))))
|
11
|
-
(setq emacs-root-path project-directory)
|
12
|
-
(setq emacs-util-path (expand-file-name "util" emacs-root-path)))
|
13
|
-
|
14
|
-
(add-to-list 'load-path emacs-root-path)
|
15
|
-
(add-to-list 'load-path (expand-file-name "espuds" emacs-util-path))
|
16
|
-
(add-to-list 'load-path (expand-file-name "ert" emacs-util-path))
|
17
|
-
|
18
|
-
(require 'vimgolf)
|
19
|
-
(require 'espuds)
|
20
|
-
(require 'ert)
|
21
|
-
|
22
|
-
|
23
|
-
(Setup
|
24
|
-
;; Before anything has run
|
25
|
-
)
|
26
|
-
|
27
|
-
(Before
|
28
|
-
;; Before each scenario is run
|
29
|
-
)
|
30
|
-
|
31
|
-
(After
|
32
|
-
;; After each scenario is run
|
33
|
-
)
|
34
|
-
|
35
|
-
(Teardown
|
36
|
-
;; After when everything has been run
|
37
|
-
)
|
data/emacs/todo.org
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
* VimGolf TODO
|
2
|
-
|
3
|
-
** Game Excersizes
|
4
|
-
|
5
|
-
** Browser
|
6
|
-
*** DONE Handle/fix character encoding
|
7
|
-
CLOSED: [2012-07-28 Sat 23:07]
|
8
|
-
:LOGBOOK:
|
9
|
-
- State "DONE" from "TODO" [2012-07-28 Sat 23:07] \\
|
10
|
-
Added a utility function to handling <, >, &, and ".
|
11
|
-
:END:
|
12
|
-
Things like < and >, etc.
|
13
|
-
*** DONE Fix line endings
|
14
|
-
CLOSED: [2012-07-28 Sat 22:51]
|
15
|
-
:LOGBOOK:
|
16
|
-
- State "DONE" from "TODO" [2012-07-28 Sat 22:51] \\
|
17
|
-
Added a function to replace ^M with some replacement (default space).
|
18
|
-
Currently only running this function on entry descriptions.
|
19
|
-
:END:
|
20
|
-
Need to convert ^M characters
|
21
|
-
*** DONE Add/fix line wrapping
|
22
|
-
CLOSED: [2012-07-28 Sat 22:04]
|
23
|
-
:LOGBOOK:
|
24
|
-
- State "DONE" from "TODO" [2012-07-28 Sat 22:04]
|
25
|
-
:END:
|
26
|
-
Can't assume that everyone's emacs will be set the same. Should really set a
|
27
|
-
particular fill-column and enforce it.
|
28
|
-
*** DONE Truncate long titles
|
29
|
-
CLOSED: [2012-07-28 Sat 22:21]
|
30
|
-
:LOGBOOK:
|
31
|
-
- State "DONE" from "IN PROGRESS" [2012-07-28 Sat 22:21]
|
32
|
-
- State "IN PROGRESS" from "TODO" [2012-07-28 Sat 22:09]
|
33
|
-
:END:
|
34
|
-
Use ellipses to truncate titles that would normally be longer than the
|
35
|
-
fill-column width.
|
36
|
-
*** DONE When first loading (via url-retrieve), list isn't showing after the call
|
37
|
-
CLOSED: [2012-07-28 Sat 23:11]
|
38
|
-
:LOGBOOK:
|
39
|
-
- State "DONE" from "TODO" [2012-07-28 Sat 23:11] \\
|
40
|
-
The list insertion was happening outside of the async callback. Now it happens
|
41
|
-
during the callback (if url-retrieve is used) and during the browse function
|
42
|
-
itself (if not).
|
43
|
-
:END:
|
44
|
-
I'm not sure if the call back isn't working or what. Manually refreshing
|
45
|
-
will display the list.
|
data/emacs/vimgolf.el
DELETED
@@ -1,488 +0,0 @@
|
|
1
|
-
;;; vimgolf.el --- VimGolf interface for the One True Editor
|
2
|
-
;; Copyright (C) never, by no one
|
3
|
-
|
4
|
-
;;; Author: Tim Visher <tim.visher@gmail.com>
|
5
|
-
;;; Maintainer: Tim Visher <tim.visher@gmail.com>
|
6
|
-
;;; Created: 2011-11-02
|
7
|
-
;;; Version: 0.10.0
|
8
|
-
;;; Keywords: games vimgolf vim
|
9
|
-
|
10
|
-
;; This file is not part of GNU Emacs
|
11
|
-
|
12
|
-
;;; Commentary:
|
13
|
-
|
14
|
-
;; This is a simple package that allows Emacs users to compete on [VimGolf][1]
|
15
|
-
;; using the One True Editor. Competition can be commenced utilizing `M-x
|
16
|
-
;; vimgolf`. When finished with a challenge, `C-c C-v C-c` should finish your
|
17
|
-
;; editing, ensure correctness, and submit your score and keystrokes to
|
18
|
-
;; [VimGolf][1].
|
19
|
-
;;
|
20
|
-
;; On second thought, let's not go to Camelot. It's a silly place.
|
21
|
-
;;
|
22
|
-
;; Patches are accepted at https://github.com/timvisher/vimgolf
|
23
|
-
;;
|
24
|
-
;; [1]: http://vimgolf.com/
|
25
|
-
|
26
|
-
;;; Installation:
|
27
|
-
|
28
|
-
;; Use package.el. You'll need to add Marmalade to your archives:
|
29
|
-
|
30
|
-
;; (require 'package)
|
31
|
-
;; (add-to-list 'package-archives
|
32
|
-
;; '("marmalade" . "http://marmalade-repo.org/packages/"))
|
33
|
-
|
34
|
-
;; If you use a version of Emacs prior to 24 that doesn't include
|
35
|
-
;; package.el, you can get it from http://bit.ly/pkg-el23. If you have
|
36
|
-
;; an older package.el installed from tromey.com, you should upgrade
|
37
|
-
;; in order to support installation from multiple sources.
|
38
|
-
|
39
|
-
;;; License:
|
40
|
-
|
41
|
-
;; [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/)
|
42
|
-
|
43
|
-
;;; Contributors
|
44
|
-
|
45
|
-
;; Tim Visher (@timvisher)
|
46
|
-
;; Steve Purcell (@sanityinc)
|
47
|
-
;; Adam Collard (@acollard)
|
48
|
-
;; Siddhanathan Shanmugam (@siddhanathan)
|
49
|
-
|
50
|
-
;;; Code:
|
51
|
-
|
52
|
-
(require 'json)
|
53
|
-
|
54
|
-
(defgroup vimgolf nil
|
55
|
-
"Compete on VimGolf with the One True Editor."
|
56
|
-
:prefix "vimgolf-"
|
57
|
-
:group 'applications)
|
58
|
-
|
59
|
-
(defcustom vimgolf-key nil
|
60
|
-
"Your VimGolf API Key. Must be set in order to submit your solution."
|
61
|
-
:type 'string
|
62
|
-
:group 'vimgolf)
|
63
|
-
|
64
|
-
(defcustom vimgolf-mode-hook '((lambda () (whitespace-mode t)))
|
65
|
-
"A list of functions to call upon the initialization of vimgolf-mode."
|
66
|
-
:type 'hook
|
67
|
-
:group 'vimgolf)
|
68
|
-
|
69
|
-
(defvar vimgolf-mode-map
|
70
|
-
(let ((map (make-sparse-keymap)))
|
71
|
-
(define-key map (kbd "C-c C-v C-c") 'vimgolf-submit)
|
72
|
-
(define-key map (kbd "C-c C-v r") 'vimgolf-revert)
|
73
|
-
(define-key map (kbd "C-c C-v d") 'vimgolf-diff)
|
74
|
-
(define-key map (kbd "C-c C-v c") 'vimgolf-continue)
|
75
|
-
(define-key map (kbd "C-c C-v p") 'vimgolf-pause)
|
76
|
-
(define-key map (kbd "C-c C-v q") 'vimgolf-quit)
|
77
|
-
map))
|
78
|
-
|
79
|
-
(define-minor-mode vimgolf-mode
|
80
|
-
"Toggle VimGolf mode.
|
81
|
-
|
82
|
-
With no argument, this command toggles the mode. Non-null prefix
|
83
|
-
argument turns on the mode. Null prefix argument turns off the
|
84
|
-
mode.
|
85
|
-
|
86
|
-
When VimGolf mode is enabled, several key bindings are defined
|
87
|
-
with `C-c C-v` prefixes to help in playing VimGolf.
|
88
|
-
|
89
|
-
\\{vimgolf-mode-map}"
|
90
|
-
;; The initial value.
|
91
|
-
nil
|
92
|
-
;; The indicator for the mode line.
|
93
|
-
" VimGolf"
|
94
|
-
;; The minor mode bindings.
|
95
|
-
:keymap vimgolf-mode-map
|
96
|
-
:group 'vimgolf)
|
97
|
-
|
98
|
-
(defvar vimgolf-challenge nil)
|
99
|
-
(defvar vimgolf-challenge-history nil)
|
100
|
-
|
101
|
-
(defvar vimgolf-prior-window-configuration nil)
|
102
|
-
|
103
|
-
(defvar vimgolf-working-window-configuration nil)
|
104
|
-
|
105
|
-
(defvar vimgolf-work-buffer-name "*vimgolf-work*")
|
106
|
-
(defvar vimgolf-start-buffer-name "*vimgolf-start*")
|
107
|
-
(defvar vimgolf-end-buffer-name "*vimgolf-end*")
|
108
|
-
(defvar vimgolf-keystrokes-buffer-name "*vimgolf-keystrokes*")
|
109
|
-
|
110
|
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
111
|
-
;; Keystroke logging
|
112
|
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
113
|
-
|
114
|
-
(defmacro vimgolf-with-saved-command-environment (&rest body)
|
115
|
-
`(let ((deactivate-mark nil)
|
116
|
-
(this-command this-command)
|
117
|
-
(last-command last-command))
|
118
|
-
,@body))
|
119
|
-
|
120
|
-
(defun vimgolf-capturable-keystroke-p ()
|
121
|
-
(not (or executing-kbd-macro
|
122
|
-
(member this-command
|
123
|
-
'(digit-argument
|
124
|
-
negative-argument
|
125
|
-
universal-argument
|
126
|
-
universal-argument-other-key
|
127
|
-
universal-argument-minus
|
128
|
-
universal-argument-more
|
129
|
-
isearch-other-meta-char))
|
130
|
-
(string-prefix-p "vimgolf-" (symbol-name this-command)))))
|
131
|
-
|
132
|
-
(defun vimgolf-capturable-dangling-keystroke-p ()
|
133
|
-
(member this-command
|
134
|
-
'(calc-dispatch)))
|
135
|
-
|
136
|
-
(defvar vimgolf-keystrokes nil
|
137
|
-
"A list of (keys-vector . command) pairs for the keystrokes entered.
|
138
|
-
|
139
|
-
Each entry is a cons cell containing a key sequence vector
|
140
|
-
suitable for use with `key-description', and a symbol for the
|
141
|
-
command that was executed as a result (which may be nil if an
|
142
|
-
unknown key sequence was entered).")
|
143
|
-
|
144
|
-
(defun vimgolf-maybe-capture-keystroke (pred)
|
145
|
-
"Store the keystrokes for `this-command' if result of calling function `PRED' is not nil."
|
146
|
-
(vimgolf-with-saved-command-environment
|
147
|
-
(when (funcall pred)
|
148
|
-
(setq vimgolf-keystrokes
|
149
|
-
(append vimgolf-keystrokes (list (cons (this-command-keys-vector)
|
150
|
-
this-command)))))))
|
151
|
-
|
152
|
-
(defun vimgolf-capture-keystroke ()
|
153
|
-
(vimgolf-maybe-capture-keystroke 'vimgolf-capturable-keystroke-p))
|
154
|
-
|
155
|
-
(defun vimgolf-capture-dangling-keystroke ()
|
156
|
-
(vimgolf-maybe-capture-keystroke 'vimgolf-capturable-dangling-keystroke-p))
|
157
|
-
|
158
|
-
(defun vimgolf-get-keystrokes-as-string (&optional separator)
|
159
|
-
(unless separator (setq separator " "))
|
160
|
-
(mapconcat 'key-description (mapcar 'car vimgolf-keystrokes) separator))
|
161
|
-
|
162
|
-
(defun vimgolf-refresh-keystroke-log ()
|
163
|
-
"Refresh the contents of the keystrokes log buffer."
|
164
|
-
(let ((deactivate-mark nil))
|
165
|
-
(with-current-buffer (get-buffer-create vimgolf-keystrokes-buffer-name)
|
166
|
-
(vimgolf-mode t)
|
167
|
-
(erase-buffer)
|
168
|
-
(insert (format "Challenge ID: %s\n%s\n\n" vimgolf-challenge (vimgolf-challenge-url vimgolf-challenge))
|
169
|
-
(format "Keystrokes (%d):\n\n" (vimgolf-count-keystrokes))
|
170
|
-
(vimgolf-get-keystrokes-as-string)
|
171
|
-
"\n\nFull command log:\n\n")
|
172
|
-
(when vimgolf-keystrokes
|
173
|
-
(let* ((descrs-and-commands
|
174
|
-
(mapcar (lambda (entry) (cons (key-description (car entry)) (cdr entry))) vimgolf-keystrokes))
|
175
|
-
(maxlen (apply 'max (mapcar 'length (mapcar 'car descrs-and-commands))))
|
176
|
-
(fmt (format "%%-%ds %%s" maxlen)))
|
177
|
-
(dolist (entry descrs-and-commands)
|
178
|
-
(insert (format fmt (car entry) (prin1-to-string (cdr entry) t)) "\n")))))))
|
179
|
-
|
180
|
-
(defun vimgolf-enable-capture (enable)
|
181
|
-
"Enable keystroke logging if `ENABLE' is non-nil otherwise disable it."
|
182
|
-
(let ((f (if enable 'add-hook 'remove-hook)))
|
183
|
-
(funcall f 'pre-command-hook 'vimgolf-capture-keystroke)
|
184
|
-
(funcall f 'post-command-hook 'vimgolf-capture-dangling-keystroke)
|
185
|
-
(funcall f 'post-command-hook 'vimgolf-refresh-keystroke-log)))
|
186
|
-
|
187
|
-
(defun vimgolf-count-keystrokes ()
|
188
|
-
(apply '+ (mapcar 'length (mapcar 'car vimgolf-keystrokes))))
|
189
|
-
|
190
|
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
191
|
-
;; Managing and scoring challenges
|
192
|
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
193
|
-
|
194
|
-
(defun vimgolf-solution-correct-p ()
|
195
|
-
"Return t if the work text is identical to the solution, nil otherwise."
|
196
|
-
(let ((working (with-current-buffer vimgolf-work-buffer-name (buffer-string)))
|
197
|
-
(end (with-current-buffer vimgolf-end-buffer-name (buffer-string))))
|
198
|
-
(string= working end)))
|
199
|
-
|
200
|
-
(defun vimgolf-wrong-solution ()
|
201
|
-
(message "Wrong!")
|
202
|
-
(vimgolf-diff))
|
203
|
-
|
204
|
-
(defun vimgolf-right-solution ()
|
205
|
-
(delete-other-windows)
|
206
|
-
(switch-to-buffer vimgolf-keystrokes-buffer-name)
|
207
|
-
(message "Hurray! You solved %s in %d keystrokes!" vimgolf-challenge (vimgolf-count-keystrokes)))
|
208
|
-
|
209
|
-
(defun vimgolf-submit ()
|
210
|
-
"Stop the challenge and attempt to submit the solution to VimGolf."
|
211
|
-
(interactive)
|
212
|
-
(vimgolf-enable-capture nil)
|
213
|
-
(if (vimgolf-solution-correct-p) (vimgolf-right-solution) (vimgolf-wrong-solution)))
|
214
|
-
|
215
|
-
(defun vimgolf-clear-keystrokes ()
|
216
|
-
(setq vimgolf-keystrokes nil))
|
217
|
-
|
218
|
-
(defun vimgolf-reset-work-buffer ()
|
219
|
-
"Reset the contents of the work buffer, and clear undo/macro history etc."
|
220
|
-
(with-current-buffer (get-buffer-create vimgolf-work-buffer-name)
|
221
|
-
(vimgolf-init-buffer (current-buffer)
|
222
|
-
(with-current-buffer vimgolf-start-buffer-name
|
223
|
-
(buffer-string)))
|
224
|
-
(when defining-kbd-macro
|
225
|
-
(end-kbd-macro))
|
226
|
-
(vimgolf-clear-keystrokes)
|
227
|
-
(setq buffer-undo-list nil)
|
228
|
-
(set-buffer-modified-p nil)))
|
229
|
-
|
230
|
-
(defun vimgolf-revert ()
|
231
|
-
"Revert the work buffer to it's original state and reset keystrokes."
|
232
|
-
(interactive)
|
233
|
-
(vimgolf-reset-work-buffer)
|
234
|
-
(set-window-configuration vimgolf-working-window-configuration)
|
235
|
-
(message "If at first you don't succeed, try, try again."))
|
236
|
-
|
237
|
-
(defun vimgolf-diff ()
|
238
|
-
"Pause the competition and view differences between the buffers."
|
239
|
-
(interactive)
|
240
|
-
(vimgolf-enable-capture nil)
|
241
|
-
(ediff-buffers (get-buffer-create vimgolf-work-buffer-name) (get-buffer-create vimgolf-end-buffer-name))
|
242
|
-
(message "Remember to `C-c C-v c` when you're done."))
|
243
|
-
|
244
|
-
(defun vimgolf-continue ()
|
245
|
-
"Restore work and end buffers and begin recording keystrokes again."
|
246
|
-
(interactive)
|
247
|
-
(vimgolf-enable-capture t)
|
248
|
-
(set-window-configuration vimgolf-working-window-configuration)
|
249
|
-
(message "Golf away!"))
|
250
|
-
|
251
|
-
(defun vimgolf-pause ()
|
252
|
-
"Stop recording keystrokes."
|
253
|
-
(interactive)
|
254
|
-
(vimgolf-enable-capture nil)
|
255
|
-
(message "Come `C-c C-v c` soon."))
|
256
|
-
|
257
|
-
(defun vimgolf-quit ()
|
258
|
-
"Cancel the competition."
|
259
|
-
(interactive)
|
260
|
-
(vimgolf-enable-capture nil)
|
261
|
-
(vimgolf-kill-existing-session)
|
262
|
-
(set-window-configuration vimgolf-prior-window-configuration)
|
263
|
-
(message "I declare you, n00b!"))
|
264
|
-
|
265
|
-
(defvar vimgolf-host "http://vimgolf.com/")
|
266
|
-
|
267
|
-
;; (setq vimgolf-host "http://vimgolf.local:8888/")
|
268
|
-
;; (setq vimgolf-host "http://vimgolf.com/")
|
269
|
-
;; Overall VimGolf Rank ID: 4d2fb20e63b08b08b0000075
|
270
|
-
;; Sort entries based on date ID: 4ea9bc988b36f70001000008
|
271
|
-
;; HTML to Haml ID: 4d3c51f1aabf526ed6000030
|
272
|
-
;; Assignment Allignment: 4d2c9d06eda6262e4e00007a
|
273
|
-
|
274
|
-
(defvar vimgolf-challenge-extension ".json")
|
275
|
-
|
276
|
-
(defun vimgolf-challenge-path (challenge-id)
|
277
|
-
(concat "challenges/" challenge-id))
|
278
|
-
|
279
|
-
(defun vimgolf-challenge-url (challenge-id)
|
280
|
-
(concat vimgolf-host (vimgolf-challenge-path challenge-id) vimgolf-challenge-extension))
|
281
|
-
|
282
|
-
(defun vimgolf-init-buffer (buffer text)
|
283
|
-
(with-current-buffer buffer
|
284
|
-
(erase-buffer)
|
285
|
-
(insert text)
|
286
|
-
(goto-char (point-min))
|
287
|
-
(vimgolf-mode t)))
|
288
|
-
|
289
|
-
(defun vimgolf-kill-existing-session ()
|
290
|
-
"Kill any vimgolf-related buffers."
|
291
|
-
(dolist (buf (list vimgolf-start-buffer-name
|
292
|
-
vimgolf-work-buffer-name
|
293
|
-
vimgolf-end-buffer-name
|
294
|
-
vimgolf-keystrokes-buffer-name))
|
295
|
-
(when (get-buffer buf)
|
296
|
-
(kill-buffer buf))))
|
297
|
-
|
298
|
-
(defun vimgolf-get-text (var response)
|
299
|
-
(format "%s" (assoc-default 'data (assq var response))))
|
300
|
-
|
301
|
-
(defun vimgolf-retrieve-challenge (challenge-id)
|
302
|
-
(interactive)
|
303
|
-
(with-current-buffer
|
304
|
-
(url-retrieve-synchronously (vimgolf-challenge-url challenge-id))
|
305
|
-
(goto-char url-http-end-of-headers)
|
306
|
-
(json-read)))
|
307
|
-
|
308
|
-
(defun vimgolf-setup (status challenge-id)
|
309
|
-
(let ((url-mime-encoding-string "identity"))
|
310
|
-
(setq vimgolf-response (vimgolf-retrieve-challenge challenge-id)))
|
311
|
-
|
312
|
-
(vimgolf-clear-keystrokes)
|
313
|
-
(setq vimgolf-prior-window-configuration (current-window-configuration)
|
314
|
-
vimgolf-challenge challenge-id)
|
315
|
-
(goto-char (point-min))
|
316
|
-
|
317
|
-
(let* ((start-text (vimgolf-get-text 'in vimgolf-response))
|
318
|
-
(end-text (vimgolf-get-text 'out vimgolf-response)))
|
319
|
-
(vimgolf-kill-existing-session)
|
320
|
-
|
321
|
-
(let ((vimgolf-start-buffer (get-buffer-create vimgolf-start-buffer-name))
|
322
|
-
(vimgolf-work-buffer (get-buffer-create vimgolf-work-buffer-name))
|
323
|
-
(vimgolf-end-buffer (get-buffer-create vimgolf-end-buffer-name)))
|
324
|
-
|
325
|
-
(vimgolf-init-buffer vimgolf-start-buffer start-text)
|
326
|
-
(vimgolf-init-buffer vimgolf-end-buffer end-text)
|
327
|
-
(with-current-buffer vimgolf-end-buffer (setq buffer-read-only t))
|
328
|
-
(vimgolf-reset-work-buffer)
|
329
|
-
|
330
|
-
;; Set up windows
|
331
|
-
(delete-other-windows)
|
332
|
-
(display-buffer vimgolf-end-buffer 'display-buffer-pop-up-window)
|
333
|
-
(set-window-buffer (selected-window) vimgolf-work-buffer)
|
334
|
-
(switch-to-buffer vimgolf-work-buffer)
|
335
|
-
(setq vimgolf-working-window-configuration (current-window-configuration))
|
336
|
-
|
337
|
-
(vimgolf-continue))))
|
338
|
-
|
339
|
-
(defvar *vimgolf-browse-list* nil
|
340
|
-
"Holds a list of parsed VimGolf challenges.")
|
341
|
-
|
342
|
-
(defun vimgolf-browse (&optional force-pull)
|
343
|
-
(interactive)
|
344
|
-
(if (or (eq *vimgolf-browse-list* nil)
|
345
|
-
force-pull)
|
346
|
-
(url-retrieve vimgolf-host 'vimgolf-parse-browse-html)
|
347
|
-
(vimgolf-browse-list)
|
348
|
-
(vimgolf-browse-next)))
|
349
|
-
|
350
|
-
(defun vimgolf-browse-refresh ()
|
351
|
-
(interactive)
|
352
|
-
(vimgolf-browse t))
|
353
|
-
|
354
|
-
(defun vimgolf-replace-control-m (string &optional replace)
|
355
|
-
(replace-regexp-in-string "
|
356
|
-
|
357
|
-
(defun vimgolf-parse-html-entites (string)
|
358
|
-
(replace-regexp-in-string
|
359
|
-
"<" "<"
|
360
|
-
(replace-regexp-in-string
|
361
|
-
">" ">"
|
362
|
-
(replace-regexp-in-string
|
363
|
-
"&" "&"
|
364
|
-
(replace-regexp-in-string
|
365
|
-
""" "\""
|
366
|
-
string)))))
|
367
|
-
|
368
|
-
(defun vimgolf-parse-browse-html (status)
|
369
|
-
(with-current-buffer (current-buffer)
|
370
|
-
(let ((html (vimgolf-parse-html-entites
|
371
|
-
(replace-regexp-in-string "\n" "" (buffer-string))))
|
372
|
-
(start 0))
|
373
|
-
(setq *vimgolf-browse-list* nil)
|
374
|
-
(while
|
375
|
-
(string-match
|
376
|
-
"<a href=\"/challenges/\\([a-zA-Z0-9]+\\)\">\\(.*?\\)</a>.*?<p>\\(.*?\\)</p>"
|
377
|
-
html)
|
378
|
-
(add-to-list '*vimgolf-browse-list*
|
379
|
-
(cons (match-string 1 html)
|
380
|
-
(list (match-string 2 html)
|
381
|
-
(vimgolf-replace-control-m
|
382
|
-
(match-string 3 html))))
|
383
|
-
t)
|
384
|
-
(setq html (substring html (match-end 0))))
|
385
|
-
*vimgolf-browse-list*))
|
386
|
-
(vimgolf-browse-list)
|
387
|
-
(vimgolf-browse-next))
|
388
|
-
|
389
|
-
(defun vimgolf-browse-list ()
|
390
|
-
(let ((browse-buffer (get-buffer-create "*VimGolf Browse*")))
|
391
|
-
(switch-to-buffer browse-buffer)
|
392
|
-
(setq buffer-read-only nil)
|
393
|
-
(kill-region (point-min) (point-max))
|
394
|
-
(insert "VimGolf Challenges")
|
395
|
-
(newline 2)
|
396
|
-
(dolist (challenge *vimgolf-browse-list*)
|
397
|
-
(let ((title (substring (cadr challenge)
|
398
|
-
0
|
399
|
-
(min (length (cadr challenge))
|
400
|
-
(- fill-column 3))))
|
401
|
-
(description (car (cdr (cdr challenge))))
|
402
|
-
(challenge-id (car challenge)))
|
403
|
-
(when (< (length title) (length (cadr challenge)))
|
404
|
-
(setq title (concat title "...")))
|
405
|
-
(insert-text-button title
|
406
|
-
'action 'vimgolf-browse-select
|
407
|
-
'follow-link t
|
408
|
-
'challenge-id challenge-id
|
409
|
-
'help-echo description))
|
410
|
-
(newline)))
|
411
|
-
(beginning-of-buffer)
|
412
|
-
(vimgolf-browse-mode))
|
413
|
-
|
414
|
-
(defun vimgolf-browse-select (arg)
|
415
|
-
(let ((challenge-id (get-text-property (point) 'challenge-id)))
|
416
|
-
(vimgolf challenge-id)))
|
417
|
-
|
418
|
-
(defun vimgolf-message-title ()
|
419
|
-
(let ((challenge-id (get-text-property (point) 'challenge-id)))
|
420
|
-
(when challenge-id
|
421
|
-
(message (cadr (assoc challenge-id *vimgolf-browse-list*))))))
|
422
|
-
|
423
|
-
(defun vimgolf-browse-next ()
|
424
|
-
(interactive)
|
425
|
-
(goto-char (next-single-property-change (point) 'challenge-id))
|
426
|
-
(unless (get-text-property (point) 'challenge-id)
|
427
|
-
(goto-char (next-single-property-change (point) 'challenge-id)))
|
428
|
-
(vimgolf-message-title))
|
429
|
-
|
430
|
-
(defun vimgolf-browse-previous ()
|
431
|
-
(interactive)
|
432
|
-
(goto-char (previous-single-property-change (point) 'challenge-id))
|
433
|
-
(unless (get-text-property (point) 'challenge-id)
|
434
|
-
(goto-char (previous-single-property-change (point) 'challenge-id)))
|
435
|
-
(vimgolf-message-title))
|
436
|
-
|
437
|
-
(defun vimgolf-show-description ()
|
438
|
-
(interactive)
|
439
|
-
(let ((challenge-id (get-text-property (point) 'challenge-id)))
|
440
|
-
(save-excursion
|
441
|
-
(setq buffer-read-only nil)
|
442
|
-
(if (text-property-any (point-min) (point-max) 'challenge-description challenge-id)
|
443
|
-
(progn
|
444
|
-
(beginning-of-buffer)
|
445
|
-
(while (not (eq (get-text-property (point) 'challenge-description) challenge-id))
|
446
|
-
(goto-char (next-single-property-change (point) 'challenge-description)))
|
447
|
-
(let ((start (point)))
|
448
|
-
(goto-char (next-single-property-change (point) 'challenge-description))
|
449
|
-
(delete-region start (point))
|
450
|
-
(delete-blank-lines)
|
451
|
-
(delete-blank-lines)))
|
452
|
-
(end-of-line)
|
453
|
-
(newline 3)
|
454
|
-
(forward-line -1)
|
455
|
-
(let ((start (point)))
|
456
|
-
(insert " " (car (cddr (assoc challenge-id *vimgolf-browse-list*))))
|
457
|
-
(fill-region start (point))
|
458
|
-
(add-text-properties start (point) `(challenge-description ,challenge-id))))
|
459
|
-
(setq buffer-read-only t))))
|
460
|
-
|
461
|
-
;;;###autoload
|
462
|
-
(defun vimgolf (challenge-id)
|
463
|
-
"Open a VimGolf Challenge"
|
464
|
-
(interactive (list (read-from-minibuffer "Challenge ID: " nil nil nil 'vimgolf-challenge-history)))
|
465
|
-
(url-retrieve (vimgolf-challenge-url challenge-id) 'vimgolf-setup `(,challenge-id)))
|
466
|
-
|
467
|
-
(defvar vimgolf-browse-mode-map (make-sparse-keymap)
|
468
|
-
"Keymap for vimgolf-mode.")
|
469
|
-
|
470
|
-
(define-derived-mode vimgolf-browse-mode special-mode "vimgolf browse"
|
471
|
-
"A major mode for completing vimgolf challenges.
|
472
|
-
|
473
|
-
\\{vimgolf-browse-mode-map}"
|
474
|
-
(define-key vimgolf-browse-mode-map (kbd "TAB") 'vimgolf-show-description)
|
475
|
-
(define-key vimgolf-browse-mode-map "g" 'vimgolf-browse-refresh)
|
476
|
-
(define-key vimgolf-browse-mode-map "n" 'vimgolf-browse-next)
|
477
|
-
(define-key vimgolf-browse-mode-map "p" 'vimgolf-browse-previous)
|
478
|
-
)
|
479
|
-
|
480
|
-
(put 'vimgolf-mode 'mode-class 'special)
|
481
|
-
|
482
|
-
(provide 'vimgolf)
|
483
|
-
|
484
|
-
;;; Local Variables:
|
485
|
-
;;; tab-width:2
|
486
|
-
;;; indent-tabs-mode:nil
|
487
|
-
;;; End:
|
488
|
-
;;; vimgolf.el ends here
|