dim.el 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. ;;; dim.el --- Change mode-line names of major/minor modes -*- lexical-binding: t -*-
  2. ;; Copyright © 2015, 2016 Alex Kost
  3. ;; Author: Alex Kost <alezost@gmail.com>
  4. ;; Created: 24 Dec 2015
  5. ;; Version: 0.1
  6. ;; URL: https://github.com/alezost/dim.el
  7. ;; Keywords: convenience
  8. ;; Package-Requires: ((emacs "24.4"))
  9. ;; This program is free software; you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation, either version 3 of the License, or
  12. ;; (at your option) any later version.
  13. ;; This program is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. ;;; Commentary:
  20. ;; The purpose of this package is to "customize" the mode-line names of
  21. ;; major and minor modes. An example of using:
  22. ;;
  23. ;; (when (require 'dim nil t)
  24. ;; (dim-major-names
  25. ;; '((emacs-lisp-mode "EL")
  26. ;; (lisp-mode "CL")
  27. ;; (Info-mode "I")
  28. ;; (help-mode "H")))
  29. ;; (dim-minor-names
  30. ;; '((auto-fill-function " ↵")
  31. ;; (isearch-mode " 🔎")
  32. ;; (whitespace-mode " _" whitespace)
  33. ;; (paredit-mode " ()" paredit)
  34. ;; (eldoc-mode "" eldoc))))
  35. ;; Along with `dim-major-names' and `dim-minor-names', you can use
  36. ;; `dim-major-name' and `dim-minor-name' to change the names by one.
  37. ;; Many thanks to the author of
  38. ;; <http://www.emacswiki.org/emacs/delight.el> package, as the code of
  39. ;; this file is heavily based on it.
  40. ;; For more verbose description, see README at
  41. ;; <https://github.com/alezost/dim.el>.
  42. ;;; Code:
  43. (defgroup dim nil
  44. "Change mode-line names of major and minor modes."
  45. :group 'convenience)
  46. (defcustom dim-everywhere nil
  47. "If non-nil, just set `mode-name' to the 'dimmed' name.
  48. If nil, try to be more clever to change the name only for the
  49. mode-line. Particularly, display the original `mode-name' in the
  50. mode description (\\[describe-mode])."
  51. :type 'boolean
  52. :group 'dim)
  53. (defvar dim-major-names nil
  54. "List of specifications for changing `mode-name'.
  55. Each element of the list should be a list of arguments taken by
  56. `dim-major-name' function.")
  57. (defvar dim-inhibit-major-name nil
  58. "If non-nil, original mode names are used instead of names from
  59. `dim-major-names' variable.")
  60. (defun dim-get-major-name (mode)
  61. "Return MODE name from `dim-major-names' variable."
  62. (cadr (assq mode dim-major-names)))
  63. (defun dim-set-major-name (&rest _)
  64. "Replace `mode-name' of the current major mode.
  65. Use the appropriate name from `dim-major-names' variable.
  66. This function ignores the arguments to make it suitable for using
  67. in advices. For example, if you changed `mode-name' of
  68. `dired-mode', you'll be surprised that it returns to \"Dired\"
  69. after exiting from `wdired-mode'. This happens because \"Dired\"
  70. string is hard-coded in `wdired-change-to-dired-mode'. This can
  71. be workaround-ed by using the following advice:
  72. (advice-add 'wdired-change-to-dired-mode :after #'dim-set-major-name)"
  73. (let ((new-name (dim-get-major-name major-mode)))
  74. (when new-name
  75. (setq mode-name
  76. (if dim-everywhere
  77. new-name
  78. `(dim-inhibit-major-name ,mode-name ,new-name))))))
  79. (add-hook 'after-change-major-mode-hook 'dim-set-major-name)
  80. (defun dim-inhibit-major-name (fun &rest args)
  81. "Apply FUN to ARGS with temporary disabled 'dimmed' major mode names.
  82. This function is intended to be used as an 'around' advice for
  83. FUN. Such advice is needed for `format-mode-line' function, as
  84. it allows to use the original `mode-name' value when it is
  85. displayed in `describe-mode' help buffer."
  86. (let ((dim-inhibit-major-name t))
  87. (apply fun args)))
  88. (advice-add 'format-mode-line :around #'dim-inhibit-major-name)
  89. (defun dim-add-or-set (var name &rest values)
  90. "Add (NAME VALUES ...) element to the value of VAR.
  91. If VAR already has NAME element, change its VALUES."
  92. (set var
  93. (cons (cons name values)
  94. (assq-delete-all name (symbol-value var)))))
  95. ;;;###autoload
  96. (defun dim-major-name (mode new-name)
  97. "Set mode-line name of the major MODE to NEW-NAME.
  98. The change will take effect next time the MODE will be enabled."
  99. (dim-add-or-set 'dim-major-names mode new-name))
  100. ;;;###autoload
  101. (defun dim-major-names (specs)
  102. "Change names of major modes according to SPECS list.
  103. Each element of the list should be a list of arguments taken by
  104. `dim-major-name' function."
  105. (if (null dim-major-names)
  106. (setq dim-major-names specs)
  107. (dolist (spec specs)
  108. (apply #'dim-major-name spec))))
  109. (defun dim--minor-name (mode new-name)
  110. "Subroutine of `dim-minor-name'."
  111. (if (not (boundp mode))
  112. (message "Unknown minor mode '%S'." mode)
  113. (dim-add-or-set 'minor-mode-alist mode new-name)))
  114. ;;;###autoload
  115. (defun dim-minor-name (mode new-name &optional file)
  116. "Set mode-line name of the minor MODE to NEW-NAME.
  117. FILE is a feature or file name where the MODE comes from. If it
  118. is specified, it is passed to `eval-after-load'. If it is nil,
  119. MODE name is changed immediately (if the MODE is available)."
  120. (if file
  121. (eval-after-load file
  122. `(dim--minor-name ',mode ',new-name))
  123. (dim--minor-name mode new-name)))
  124. ;;;###autoload
  125. (defun dim-minor-names (specs)
  126. "Change names of minor modes according to SPECS list.
  127. Each element of the list should be a list of arguments taken by
  128. `dim-minor-name' function."
  129. (dolist (spec specs)
  130. (apply #'dim-minor-name spec)))
  131. (provide 'dim)
  132. ;;; dim.el ends here