146 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
| ;;; cheatsheet.el --- create your own cheatsheet
 | |
| 
 | |
| ;; Copyright (C) 2015 Shirin Nikita and contributors
 | |
| ;;
 | |
| ;; Author: Shirin Nikita <shirin.nikita@gmail.com> and contributors
 | |
| ;; URL: http://github.com/darksmile/cheatsheet/
 | |
| ;; Package-Version: 20151203.151
 | |
| ;; Package-Requires: ((emacs "24") (cl-lib "0.5"))
 | |
| ;; Version: 1.0
 | |
| ;; Keywords: convenience, usability
 | |
| 
 | |
| ;; This file is not part of GNU Emacs
 | |
| 
 | |
| ;;; Licence:
 | |
| 
 | |
| ;; Licensed under the same terms as Emacs.
 | |
| 
 | |
| ;;; Commentary:
 | |
| 
 | |
| ;; Quick start:
 | |
| ;; Load package
 | |
| ;; Add your first cheat:
 | |
| ;; (cheatsheet-add :group 'Common
 | |
| ;;                 :key "C-x C-c"
 | |
| ;;                 :description "leave Emacs.")
 | |
| ;; Run (cheatsheet-show) and enjoy looking at your own Emacs cheatsheet.
 | |
| 
 | |
| ;;; Code:
 | |
| 
 | |
| (require 'cl-lib)
 | |
| 
 | |
| (defconst cheatsheet--group-face
 | |
|   '(:foreground "red")
 | |
|   "Group name font face.")
 | |
| 
 | |
| (defconst cheatsheet--key-face
 | |
|   '(:foreground "orange")
 | |
|   "Cheat key font face.")
 | |
| 
 | |
| (defconst cheatsheet--keymap
 | |
|   (let ((map (make-sparse-keymap)))
 | |
|     (define-key map (kbd "C-q") 'kill-buffer-and-window)
 | |
|     map))
 | |
| 
 | |
| 
 | |
| (defvar cheatsheet--cheat-list '()
 | |
|   "List of cheats.")
 | |
| 
 | |
| ;; Getters for CHEAT and GROUP plists
 | |
| (defun cheatsheet--if-symbol-to-string (string-like)
 | |
|   "Convert STRING-LIKE to string."
 | |
|   (if (symbolp string-like) (symbol-name string-like) string-like))
 | |
| 
 | |
| (defun cheatsheet--group-name (group)
 | |
|   "Get GROUP name."
 | |
|   (cheatsheet--if-symbol-to-string (plist-get group :name)))
 | |
| 
 | |
| (defun cheatsheet--group-cheats (group)
 | |
|   "Get GROUP cheats."
 | |
|   (cheatsheet--if-symbol-to-string (plist-get group :cheats)))
 | |
| 
 | |
| (defun cheatsheet--cheat-key (cheat)
 | |
|   "Get CHEAT key."
 | |
|   (cheatsheet--if-symbol-to-string (plist-get cheat :key)))
 | |
| 
 | |
| (defun cheatsheet--cheat-group (cheat)
 | |
|   "Get CHEAT group."
 | |
|   (cheatsheet--if-symbol-to-string (plist-get cheat :group)))
 | |
| 
 | |
| (defun cheatsheet--cheat-description (cheat)
 | |
|   "Get CHEAT description."
 | |
|   (cheatsheet--if-symbol-to-string (plist-get cheat :description)))
 | |
| 
 | |
| ;; Functions to get data from CHEATSHEET in convenient format
 | |
| (defun cheatsheet--cheat-groups ()
 | |
|   "Get all groups, submitted to cheatsheet."
 | |
|   (reverse (delete-dups
 | |
|             (mapcar 'cheatsheet--cheat-group
 | |
|                     cheatsheet--cheat-list))))
 | |
| 
 | |
| (defun cheatsheet--get-group (group)
 | |
|   "Get group struct with all cheats, belonging to GROUP."
 | |
|   (cl-flet ((is-current-group (cheat)
 | |
|                               (if (string= (cheatsheet--cheat-group cheat)
 | |
|                                            group)
 | |
|                                   cheat
 | |
|                                 nil)))
 | |
|     (delq nil (mapcar #'is-current-group cheatsheet--cheat-list))))
 | |
| 
 | |
| ;; Functions to format cheatsheet items and prepare to print
 | |
| (defun cheatsheet--format-cheat (cheat key-cell-length)
 | |
|   "Format CHEAT row with KEY-CELL-LENGTH key cell length."
 | |
|   (let* ((format-string (format "%%%ds - %%s\n" key-cell-length))
 | |
|          (key (cheatsheet--cheat-key cheat))
 | |
|          (description (cheatsheet--cheat-description cheat))
 | |
|          (faced-key (propertize key 'face cheatsheet--key-face)))
 | |
|     (format format-string faced-key description)))
 | |
| 
 | |
| (defun cheatsheet--format-group (group)
 | |
|   "Format GROUP to table."
 | |
|   (cl-flet ((key-length (cheat) (length (cheatsheet--cheat-key cheat)))
 | |
|             (format-cheat (key-cell-length cheat)
 | |
|                           (cheatsheet--format-cheat cheat key-cell-length)))
 | |
| 
 | |
|     (let* ((name (cheatsheet--group-name group))
 | |
|            (cheats (cheatsheet--group-cheats group))
 | |
|            (key-max-length (apply 'max (mapcar #'key-length cheats)))
 | |
|            (key-cell-length (+ 2 key-max-length))
 | |
|            (format-cheat (apply-partially #'format-cheat key-cell-length))
 | |
|            (formatted-cheats (apply 'concat (mapcar format-cheat cheats)))
 | |
|            (faced-group-name (propertize name 'face cheatsheet--group-face)))
 | |
|       (concat faced-group-name "\n" formatted-cheats "\n"))))
 | |
| 
 | |
| (defun cheatsheet--format ()
 | |
|   "Print the whole cheatsheet."
 | |
|   (let* ((cheatsheet (cheatsheet-get))
 | |
|          (formatted-groups (mapcar 'cheatsheet--format-group cheatsheet))
 | |
|          (formatted-cheatsheet (apply 'concat formatted-groups)))
 | |
|     formatted-cheatsheet))
 | |
| 
 | |
| ;; Interface
 | |
| ;;;###autoload
 | |
| (defun cheatsheet-add (&rest cheat)
 | |
|   "Add CHEAT to cheatsheet."
 | |
|   (add-to-list 'cheatsheet--cheat-list cheat))
 | |
| 
 | |
| (defun cheatsheet-get ()
 | |
|   "Get cheatsheet as list of group structs, keeping defining order."
 | |
|   (cl-flet ((make-group (group)
 | |
|                         (list :name group
 | |
|                               :cheats (cheatsheet--get-group group))))
 | |
|     (mapcar #'make-group (cheatsheet--cheat-groups))))
 | |
| 
 | |
| ;;;###autoload
 | |
| (defun cheatsheet-show ()
 | |
|   "Create buffer and show cheatsheet."
 | |
|   (interactive)
 | |
|   (switch-to-buffer-other-window "*cheatsheet*")
 | |
|   (use-local-map cheatsheet--keymap)
 | |
|   (erase-buffer)
 | |
|   (insert (cheatsheet--format))
 | |
|   (setq buffer-read-only t))
 | |
| 
 | |
| (provide 'cheatsheet)
 | |
| ;;; cheatsheet.el ends here
 |