From afb4172ae54795fe76a984c655abf99be785040d Mon Sep 17 00:00:00 2001 From: Lucas Sta Maria Date: Fri, 2 Feb 2024 17:26:15 -0500 Subject: [PATCH] feat(emacs): make `grade-start` featureful Signed-off-by: Lucas Sta Maria --- .emacs.d/include/misc.el | 58 +++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/.emacs.d/include/misc.el b/.emacs.d/include/misc.el index 541e734..473eaa3 100644 --- a/.emacs.d/include/misc.el +++ b/.emacs.d/include/misc.el @@ -11,6 +11,7 @@ (require 'elfeed) (require 'neotree) (require 'copilot) +(require 'seq) (defun config-compile () "(Re)compile the current Emacs configuration." @@ -183,34 +184,71 @@ ("XXXX*" . "#ffffff"))) ;; Grading +(defconst grading-directory-root "pl-grading" + "The root grading directory repository.") + +(defun grade-file-format (num) + "Format NUM to a file in the grading directory." + (unless (eq major-mode 'dired-mode) + (error "Must be in Dired directory")) + (let* ((dir (dired-current-directory)) + (dir-files (directory-files dir)) + (extension ".rkt") + (all-rkt-files (-filter (lambda (f) (string= (file-name-extension f) "rkt")) + dir-files)) + (all-rkt-files+ (-map #'file-name-sans-extension all-rkt-files)) + (hw-files (-filter (lambda (f) (not (zerop (string-to-number f)))) all-rkt-files+)) + (hw-files+ (seq-sort-by #'length #'> hw-files)) + (digits (length (car hw-files+))) + (str-format (format "%%0%dd.rkt" digits))) + (format str-format num))) + (defun grade-next (&optional inc) "Go to the next homework by INC to grade." (interactive) (let ((inc (or inc 1)) - (grading-directory "pl-grading") (extension ".rkt") (filepath (buffer-file-name (current-buffer)))) - (if (not (and (string-match-p grading-directory filepath) + (if (not (and (string-match-p grading-directory-root filepath) (string-match-p extension filepath))) - (message (format "not in %s!" grading-directory)) - (let* ((target-directory (file-name-directory filepath)) + (message (format "not in %s!" grading-directory-root)) + (let* ((target-directory (file-name-directory filepath)) (filename-parts (string-split filepath "/")) (source-filename (-last-item filename-parts)) (source-number-str (file-name-sans-extension source-filename)) (source-number (string-to-number source-number-str)) (target-number (+ inc source-number)) - (target-number-str (format "%02d" target-number)) - (target-filename (format "%s.rkt" target-number-str)) + (target-filename (grade-file-format target-number)) (target-filepath (concat target-directory target-filename))) - (if (file-exists-p target-filepath) + (if (file-exists-p target-filepath) (find-file target-filepath) (message (format "next grading file doesn't exist!"))))))) -(defun start-grading () - "Start grading." +(defun grade-start (&optional start) + "Start grading in the current directory with homework START." (interactive) (keymap-global-set "C-c f" #'grade-next) - (keymap-global-set "C-c b" (lambda () (interactive) (grade-next -1)))) + (keymap-global-set "C-c b" (lambda () (interactive) (grade-next -1))) + + (let* ((start (or start 1)) + (dir (if (eq major-mode 'dired-mode) + (dired-current-directory) + (error "Must be in Dired directory"))) + (dir-path (file-name-directory dir))) + (if (not (string-match-p grading-directory-root dir-path)) + (error "Must be in subdirectory of %s" grading-directory-root) + (let ((readme-file (concat dir-path "README.md")) + (solution-file (concat dir-path "solution.rkt")) + (start-file (concat dir-path (grade-file-format start)))) + (find-file start-file) + (delete-other-windows) + (split-window-right) + (split-window-right) + (balance-windows) + (windmove-right) + (find-file solution-file) + (windmove-right) + (find-file readme-file))))) (provide 'misc) ;;; misc.el ends here