Aurebesh typing test for emacs

This entry is part 3 of 3 in the series Aurebesh

A few weeks ago, I posted the Aurebesh typing test. Since I’ve recently started learning elisp, I figured that I should implement the typing test as a feature for emacs.

The code below is terrible with bugs and problems, but heck, it’s my first elisp program after all. My goal is to improve the version over time and to add features such as logging results in a separate file and displaying a progress statistic. To use it, you’ll need to first install the Aurebesh font.

(setq correct 0)
(setq wrong 0)
(setq seconds-left 60)
(setq test-start t)

(require 'widget)

(defun aurebesh-typing-test ()
  "Aurebesh typing test"
  (interactive)
  (get-buffer-create "*Aurebesh typing test*")
  (custom/reset-aurebesh-typing-test-vars)
  (custom/aurebesh-typing-test))

(defun custom/reset-aurebesh-typing-test-vars()
  (setq test-start t)
  (setq correct 0)
  (setq wrong 0)
  (setq seconds-left 60))

(defun custom/aurebesh-typing-test()
  (with-current-buffer "*Aurebesh typing test*"
    (custom/setup-buffer)
    (custom/refresh-seconds)
    (custom/create-line-with-widget)
    (insert "Correct / wrong answers: " (number-to-string correct) " / " (number-to-string wrong) " \n")
    (custom/setup-widget)
    (custom/set-aurebesh)))

(defun custom/setup-buffer()
  (kill-all-local-variables)
  (let ((inhibit-read-only t))
    (erase-buffer))
  (remove-overlays))

(defun custom/refresh-seconds()
  (with-no-warnings
    (goto-line 1)
    (custom/delete-line)
    (insert "Seconds: " (number-to-string seconds-left) "\n")))

(defun custom/delete-line()
  (let ((beg (point)))
    (forward-line 1)
    (delete-region beg (point))))

(defun custom/create-line-with-widget()
  (if (> seconds-left 0)
      (setq randomChar (custom/get-random-char))
    (setq randomChar ""))
  (widget-insert randomChar)
  (widget-insert "\t")
  (widget-create 'editable-field
		 :size 15
		 :correct (string randomChar)
		 :notify 'custom/check-input-value)
  (widget-insert "\n"))

(defun custom/setup-widget()
  (use-local-map widget-keymap)
  (widget-setup)
  (widget-forward 1))

(defun custom/set-aurebesh()
  "Sets the aurebesh font in current buffer"
  (interactive)
  (setq buffer-face-mode-face '(:family "Aurebesh"))
  (buffer-face-mode))

(defun custom/check-input-value(widget &rest ignore)
  "Compare aurebesh input character with requested one."
  (cond
   ((string-match 
     (widget-get widget :correct)
     (widget-value widget))
    (custom/correct-input widget))
   ((not(= (length (widget-value widget)) 0))
    (custom/wrong-input))))

(defun custom/correct-input(widget)
  (if test-start
      (progn
	(custom/start-timer)
	(setq test-start nil)))
  (if (> seconds-left 0)
      (progn
	(setq correct (+ correct 1))
	(custom/next-character widget))))

(defun custom/start-timer()
  "Start Aurebesh test"
  (setq seconds-left 60)
  (setq timer (run-with-timer 0 1 'custom/decrement-seconds)))

(defun custom/decrement-seconds()
  (with-current-buffer "*Aurebesh typing test*"
    (if (> seconds-left 0)
;	(progn
	  (setq seconds-left (- seconds-left 1))
;	  (custom/refresh-seconds)
;	  (widget-forward 1))
      (custom/stop-aurebesh-typing-test))))

(defun custom/stop-aurebesh-typing-test()
  (with-current-buffer "*Aurebesh typing test*"
  (custom/refresh-seconds)
  (cancel-timer timer)
  (custom/set-arial)))

(defun custom/set-arial()
   "Sets the arial font in current buffer"
   (interactive)
   (setq buffer-face-mode-face '(:family "Arial"))
   (buffer-face-mode))

(defun custom/next-character(widget)
  (with-current-buffer "*Aurebesh typing test*"
    (custom/fill-random-character widget)
    (custom/fill-correct-wrong-answers)
    (custom/refresh-seconds)
    (widget-forward 1)
    ))

(defun custom/fill-random-character(widget)
  (with-no-warnings
    (goto-line 2))
  (delete-char 1)
  (if (> seconds-left 0)
      (setq randomChar (custom/get-random-char))
    (setq randomChar ""))
  (widget-insert randomChar)
  (widget-put widget :correct (string randomChar))
  (widget-value-set widget ""))

(defun custom/get-random-char ()
  "Insert a random alphanumeric character.."
  (let ((mycharset "abcdefghijklmnopqrstyvwxyz"))
    (elt mycharset (random (length mycharset)))))

(defun custom/fill-correct-wrong-answers()
  (with-no-warnings
    (goto-line 3))
  (kill-line)
  (insert "Correct / wrong answers: " (number-to-string correct) " / " (number-to-string wrong) " \n"))
  
(defun custom/wrong-input()
  (message "%s" (widget-get widget :correct))
  (widget-value-set widget "")
  (setq wrong (+ wrong 1)))
Series Navigation<< Aurebesh typing test

Leave a Reply

Your email address will not be published. Required fields are marked *