emacs/vimgolf.el in vimgolf-0.4.1 vs emacs/vimgolf.el in vimgolf-0.4.2
- old
+ new
@@ -1,13 +1,12 @@
;;; vimgolf.el --- VimGolf interface for the One True Editor
-
;; Copyright (C) never, by no one
;;; Author: Tim Visher <tim.visher@gmail.com>
;;; Maintainer: Tim Visher <tim.visher@gmail.com>
;;; Created: 2011-11-02
-;;; Version: 0.9.2
+;;; Version: 0.9.3
;;; Keywords: games vimgolf vim
;; This file is not part of GNU Emacs
;;; Commentary:
@@ -121,11 +120,12 @@
'(digit-argument
negative-argument
universal-argument
universal-argument-other-key
universal-argument-minus
- universal-argument-more))
+ universal-argument-more
+ isearch-other-meta-char))
(string-prefix-p "vimgolf-" (symbol-name this-command)))))
(defun vimgolf-capturable-dangling-keystroke-p ()
(member this-command
'(calc-dispatch)))
@@ -150,19 +150,23 @@
(vimgolf-maybe-capture-keystroke 'vimgolf-capturable-keystroke-p))
(defun vimgolf-capture-dangling-keystroke ()
(vimgolf-maybe-capture-keystroke 'vimgolf-capturable-dangling-keystroke-p))
+(defun vimgolf-get-keystrokes-as-string (&optional separator)
+ (unless separator (setq separator " "))
+ (mapconcat 'key-description (mapcar 'car vimgolf-keystrokes) separator))
+
(defun vimgolf-refresh-keystroke-log ()
"Refresh the contents of the keystrokes log buffer."
(let ((deactivate-mark nil))
(with-current-buffer (get-buffer-create vimgolf-keystrokes-buffer-name)
(vimgolf-mode t)
(erase-buffer)
(insert (format "Challenge ID: %s\n%s\n\n" vimgolf-challenge (vimgolf-challenge-url vimgolf-challenge))
(format "Keystrokes (%d):\n\n" (vimgolf-count-keystrokes))
- (mapconcat 'key-description (mapcar 'car vimgolf-keystrokes) " ")
+ (vimgolf-get-keystrokes-as-string)
"\n\nFull command log:\n\n")
(when vimgolf-keystrokes
(let* ((descrs-and-commands
(mapcar (lambda (entry) (cons (key-description (car entry)) (cdr entry))) vimgolf-keystrokes))
(maxlen (apply 'max (mapcar 'length (mapcar 'car descrs-and-commands))))
@@ -326,14 +330,151 @@
(switch-to-buffer vimgolf-work-buffer)
(setq vimgolf-working-window-configuration (current-window-configuration))
(vimgolf-continue))))
+(defvar *vimgolf-browse-list* nil
+ "Holds a list of parsed VimGolf challenges.")
+
+(defun vimgolf-browse (&optional force-pull)
+ (interactive)
+ (if (or (eq *vimgolf-browse-list* nil)
+ force-pull)
+ (url-retrieve vimgolf-host 'vimgolf-parse-browse-html)
+ (vimgolf-browse-list)
+ (vimgolf-browse-next)))
+
+(defun vimgolf-browse-refresh ()
+ (interactive)
+ (vimgolf-browse t))
+
+(defun vimgolf-replace-control-m (string &optional replace)
+ (replace-regexp-in-string "
" (or replace " ") string))
+
+(defun vimgolf-parse-html-entites (string)
+ (replace-regexp-in-string
+ "<" "<"
+ (replace-regexp-in-string
+ ">" ">"
+ (replace-regexp-in-string
+ "&" "&"
+ (replace-regexp-in-string
+ """ "\""
+ string)))))
+
+(defun vimgolf-parse-browse-html (status)
+ (with-current-buffer (current-buffer)
+ (let ((html (vimgolf-parse-html-entites
+ (replace-regexp-in-string "\n" "" (buffer-string))))
+ (start 0))
+ (setq *vimgolf-browse-list* nil)
+ (while
+ (string-match
+ "<a href=\"/challenges/\\([a-zA-Z0-9]+\\)\">\\(.*?\\)</a>.*?<p>\\(.*?\\)</p>"
+ html)
+ (add-to-list '*vimgolf-browse-list*
+ (cons (match-string 1 html)
+ (list (match-string 2 html)
+ (vimgolf-replace-control-m
+ (match-string 3 html))))
+ t)
+ (setq html (substring html (match-end 0))))
+ *vimgolf-browse-list*))
+ (vimgolf-browse-list)
+ (vimgolf-browse-next))
+
+(defun vimgolf-browse-list ()
+ (let ((browse-buffer (get-buffer-create "*VimGolf Browse*")))
+ (switch-to-buffer browse-buffer)
+ (setq buffer-read-only nil)
+ (kill-region (point-min) (point-max))
+ (insert "VimGolf Challenges")
+ (newline 2)
+ (dolist (challenge *vimgolf-browse-list*)
+ (let ((title (substring (cadr challenge)
+ 0
+ (min (length (cadr challenge))
+ (- fill-column 3))))
+ (description (car (cdr (cdr challenge))))
+ (challenge-id (car challenge)))
+ (when (< (length title) (length (cadr challenge)))
+ (setq title (concat title "...")))
+ (insert-text-button title
+ 'action 'vimgolf-browse-select
+ 'follow-link t
+ 'challenge-id challenge-id
+ 'help-echo description))
+ (newline)))
+ (beginning-of-buffer)
+ (vimgolf-browse-mode))
+
+(defun vimgolf-browse-select (arg)
+ (let ((challenge-id (get-text-property (point) 'challenge-id)))
+ (vimgolf challenge-id)))
+
+(defun vimgolf-message-title ()
+ (let ((challenge-id (get-text-property (point) 'challenge-id)))
+ (when challenge-id
+ (message (cadr (assoc challenge-id *vimgolf-browse-list*))))))
+
+(defun vimgolf-browse-next ()
+ (interactive)
+ (goto-char (next-single-property-change (point) 'challenge-id))
+ (unless (get-text-property (point) 'challenge-id)
+ (goto-char (next-single-property-change (point) 'challenge-id)))
+ (vimgolf-message-title))
+
+(defun vimgolf-browse-previous ()
+ (interactive)
+ (goto-char (previous-single-property-change (point) 'challenge-id))
+ (unless (get-text-property (point) 'challenge-id)
+ (goto-char (previous-single-property-change (point) 'challenge-id)))
+ (vimgolf-message-title))
+
+(defun vimgolf-show-description ()
+ (interactive)
+ (let ((challenge-id (get-text-property (point) 'challenge-id)))
+ (save-excursion
+ (setq buffer-read-only nil)
+ (if (text-property-any (point-min) (point-max) 'challenge-description challenge-id)
+ (progn
+ (beginning-of-buffer)
+ (while (not (eq (get-text-property (point) 'challenge-description) challenge-id))
+ (goto-char (next-single-property-change (point) 'challenge-description)))
+ (let ((start (point)))
+ (goto-char (next-single-property-change (point) 'challenge-description))
+ (delete-region start (point))
+ (delete-blank-lines)
+ (delete-blank-lines)))
+ (end-of-line)
+ (newline 3)
+ (forward-line -1)
+ (let ((start (point)))
+ (insert " " (car (cddr (assoc challenge-id *vimgolf-browse-list*))))
+ (fill-region start (point))
+ (add-text-properties start (point) `(challenge-description ,challenge-id))))
+ (setq buffer-read-only t))))
+
;;;###autoload
(defun vimgolf (challenge-id)
"Open a VimGolf Challenge"
(interactive (list (read-from-minibuffer "Challenge ID: " nil nil nil 'vimgolf-challenge-history)))
(url-retrieve (vimgolf-challenge-url challenge-id) 'vimgolf-setup `(,challenge-id)))
+
+(defvar vimgolf-browse-mode-map (make-sparse-keymap)
+ "Keymap for vimgolf-mode.")
+
+(define-derived-mode vimgolf-browse-mode special-mode "vimgolf browse"
+ "A major mode for completing vimgolf challenges.
+
+\\{vimgolf-browse-mode-map}"
+ (define-key vimgolf-browse-mode-map (kbd "TAB") 'vimgolf-show-description)
+ (define-key vimgolf-browse-mode-map "g" 'vimgolf-browse-refresh)
+ (define-key vimgolf-browse-mode-map "n" 'vimgolf-browse-next)
+ (define-key vimgolf-browse-mode-map "p" 'vimgolf-browse-previous)
+)
+
+(put 'vimgolf-mode 'mode-class 'special)
(provide 'vimgolf)
;;; Local Variables:
;;; tab-width:2