Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
10 KiB

  1. ;;; highlight-indentation.el --- Minor modes for highlighting indentation
  2. ;; Author: Anton Johansson <anton.johansson@gmail.com> - http://antonj.se
  3. ;; Created: Dec 15 23:42:04 2010
  4. ;; Version: 0.7.0
  5. ;; Package-Version: 0.7.0
  6. ;; Package-Commit: cd6d8168ccb04c6c0394f42e9512c58f23c01689
  7. ;; URL: https://github.com/antonj/Highlight-Indentation-for-Emacs
  8. ;;
  9. ;; This program is free software; you can redistribute it and/or
  10. ;; modify it under the terms of the GNU General Public License as
  11. ;; published by the Free Software Foundation; either version 2 of
  12. ;; the License, or (at your option) any later version.
  13. ;;
  14. ;; This program is distributed in the hope that it will be
  15. ;; useful, but WITHOUT ANY WARRANTY; without even the implied
  16. ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  17. ;; PURPOSE. See the GNU General Public License for more details.
  18. ;;
  19. ;;; Commentary:
  20. ;; Customize `highlight-indentation-face', and
  21. ;; `highlight-indentation-current-column-face' to suit your theme.
  22. ;;; Code:
  23. (defgroup highlight-indentation nil
  24. "Highlight Indentation"
  25. :prefix "highlight-indentation-"
  26. :group 'basic-faces)
  27. (defface highlight-indentation-face
  28. ;; Fringe has non intrusive color in most color-themes
  29. '((t :inherit fringe))
  30. "Basic face for highlighting indentation guides."
  31. :group 'highlight-indentation)
  32. (defcustom highlight-indentation-offset 4
  33. "Default indentation offset, used if no other can be found from
  34. major mode. This value is always used by
  35. `highlight-indentation-mode' if set buffer local. Set buffer
  36. local with `highlight-indentation-set-offset'"
  37. :group 'highlight-indentation)
  38. (defconst highlight-indentation-hooks
  39. '((after-change-functions (lambda (start end length)
  40. (highlight-indentation-redraw-region
  41. start end
  42. 'highlight-indentation-overlay
  43. 'highlight-indentation-put-overlays-region))
  44. t t)
  45. (window-scroll-functions (lambda (win start)
  46. (highlight-indentation-redraw-window
  47. win
  48. 'highlight-indentation-overlay
  49. 'highlight-indentation-put-overlays-region
  50. start))
  51. nil t)))
  52. (defun highlight-indentation-get-buffer-windows (&optional all-frames)
  53. "Return a list of windows displaying the current buffer."
  54. (get-buffer-window-list (current-buffer) 'no-minibuf all-frames))
  55. (defun highlight-indentation-delete-overlays-buffer (overlay)
  56. "Delete all overlays in the current buffer."
  57. (save-restriction
  58. (widen)
  59. (highlight-indentation-delete-overlays-region (point-min) (point-max) overlay)))
  60. (defun highlight-indentation-delete-overlays-region (start end overlay)
  61. "Delete overlays between START and END."
  62. (mapc #'(lambda (o)
  63. (if (overlay-get o overlay) (delete-overlay o)))
  64. (overlays-in start end)))
  65. (defun highlight-indentation-redraw-window (win overlay func &optional start)
  66. "Redraw win starting from START."
  67. (highlight-indentation-redraw-region (or start (window-start win)) (window-end win t) overlay func))
  68. (defun highlight-indentation-redraw-region (start end overlay func)
  69. "Erease and read overlays between START and END."
  70. (save-match-data
  71. (save-excursion
  72. (let ((inhibit-point-motion-hooks t)
  73. (end (save-excursion (goto-char end) (line-beginning-position 2))))
  74. (highlight-indentation-delete-overlays-region start end overlay)
  75. (funcall func start end overlay)))))
  76. (defun highlight-indentation-redraw-all-windows (overlay func &optional all-frames)
  77. "Redraw the all windows showing the current buffer."
  78. (dolist (win (highlight-indentation-get-buffer-windows all-frames))
  79. (highlight-indentation-redraw-window win overlay func)))
  80. (defun highlight-indentation-put-overlays-region (start end overlay)
  81. "Place overlays between START and END."
  82. (goto-char start)
  83. (let (o ;; overlay
  84. (last-indent 0)
  85. (pos start))
  86. (while (< pos end)
  87. (beginning-of-line)
  88. (while (and (integerp (char-after))
  89. (not (= 10 (char-after))) ;; newline
  90. (= 32 (char-after))) ;; space
  91. (when (= 0 (% (current-column) highlight-indentation-offset))
  92. (setq pos (point)
  93. last-indent pos
  94. o (make-overlay pos (+ pos 1)))
  95. (overlay-put o overlay t)
  96. (overlay-put o 'priority highlight-indentation-overlay-priority)
  97. (overlay-put o 'face 'highlight-indentation-face))
  98. (forward-char))
  99. (forward-line) ;; Next line
  100. (setq pos (point)))))
  101. (defun highlight-indentation-guess-offset ()
  102. "Get indentation offset of current buffer"
  103. (cond ((and (eq major-mode 'python-mode) (boundp 'python-indent))
  104. python-indent)
  105. ((and (eq major-mode 'python-mode) (boundp 'py-indent-offset))
  106. py-indent-offset)
  107. ((and (eq major-mode 'python-mode) (boundp 'python-indent-offset))
  108. python-indent-offset)
  109. ((eq major-mode 'ruby-mode)
  110. ruby-indent-level)
  111. ((and (eq major-mode 'scala-mode) (boundp 'scala-indent:step))
  112. scala-indent:step)
  113. ((and (eq major-mode 'scala-mode) (boundp 'scala-mode-indent:step))
  114. scala-mode-indent:step)
  115. ((or (eq major-mode 'scss-mode) (eq major-mode 'css-mode))
  116. css-indent-offset)
  117. ((eq major-mode 'nxml-mode)
  118. nxml-child-indent)
  119. ((eq major-mode 'coffee-mode)
  120. coffee-tab-width)
  121. ((eq major-mode 'js-mode)
  122. js-indent-level)
  123. ((eq major-mode 'js2-mode)
  124. js2-basic-offset)
  125. ((and (fboundp 'derived-mode-class) (eq (derived-mode-class major-mode) 'sws-mode))
  126. sws-tab-width)
  127. ((eq major-mode 'web-mode)
  128. web-mode-html-offset) ; other similar vars: web-mode-{css-indent,scripts}-offset
  129. ((local-variable-p 'c-basic-offset)
  130. c-basic-offset)
  131. (t
  132. (default-value 'highlight-indentation-offset))))
  133. ;;;###autoload
  134. (define-minor-mode highlight-indentation-mode
  135. "Highlight indentation minor mode highlights indentation based on spaces"
  136. :lighter " ||"
  137. (when (not highlight-indentation-mode) ;; OFF
  138. (highlight-indentation-delete-overlays-buffer 'highlight-indentation-overlay)
  139. (dolist (hook highlight-indentation-hooks)
  140. (remove-hook (car hook) (nth 1 hook) (nth 3 hook))))
  141. (when highlight-indentation-mode ;; ON
  142. (when (not (local-variable-p 'highlight-indentation-offset))
  143. (set (make-local-variable 'highlight-indentation-offset)
  144. (highlight-indentation-guess-offset)))
  145. ;; Setup hooks
  146. (dolist (hook highlight-indentation-hooks)
  147. (apply 'add-hook hook))
  148. (highlight-indentation-redraw-all-windows 'highlight-indentation-overlay
  149. 'highlight-indentation-put-overlays-region)))
  150. ;;;###autoload
  151. (defun highlight-indentation-set-offset (offset)
  152. "Set indentation offset localy in buffer, will prevent
  153. highlight-indentation from trying to guess indentation offset
  154. from major mode"
  155. (interactive
  156. (if (and current-prefix-arg (not (consp current-prefix-arg)))
  157. (list (prefix-numeric-value current-prefix-arg))
  158. (list (read-number "Indentation offset: "))))
  159. (set (make-local-variable 'highlight-indentation-offset) offset)
  160. (when highlight-indentation-mode
  161. (highlight-indentation-mode)))
  162. ;;; This minor mode will highlight the indentation of the current line
  163. ;;; as a vertical bar (grey background color) aligned with the column of the
  164. ;;; first character of the current line.
  165. (defface highlight-indentation-current-column-face
  166. ;; Fringe has non intrusive color in most color-themes
  167. '((t (:background "black")))
  168. "Basic face for highlighting indentation guides."
  169. :group 'highlight-indentation)
  170. (defvar highlight-indentation-overlay-priority 1)
  171. (defvar highlight-indentation-current-column-overlay-priority 2)
  172. (defconst highlight-indentation-current-column-hooks
  173. '((post-command-hook (lambda ()
  174. (highlight-indentation-redraw-all-windows 'highlight-indentation-current-column-overlay
  175. 'highlight-indentation-current-column-put-overlays-region)) nil t)))
  176. (defun highlight-indentation-current-column-put-overlays-region (start end overlay)
  177. "Place overlays between START and END."
  178. (let (o ;; overlay
  179. (last-indent 0)
  180. (indent (save-excursion (back-to-indentation) (current-column)))
  181. (pos start))
  182. (goto-char start)
  183. ;; (message "doing it %d" indent)
  184. (while (< pos end)
  185. (beginning-of-line)
  186. (while (and (integerp (char-after))
  187. (not (= 10 (char-after))) ;; newline
  188. (= 32 (char-after))) ;; space
  189. (when (= (current-column) indent)
  190. (setq pos (point)
  191. last-indent pos
  192. o (make-overlay pos (+ pos 1)))
  193. (overlay-put o overlay t)
  194. (overlay-put o 'priority highlight-indentation-current-column-overlay-priority)
  195. (overlay-put o 'face 'highlight-indentation-current-column-face))
  196. (forward-char))
  197. (forward-line) ;; Next line
  198. (setq pos (point)))))
  199. ;;;###autoload
  200. (define-minor-mode highlight-indentation-current-column-mode
  201. "Hilight Indentation minor mode displays a vertical bar
  202. corresponding to the indentation of the current line"
  203. :lighter " |"
  204. (when (not highlight-indentation-current-column-mode) ;; OFF
  205. (highlight-indentation-delete-overlays-buffer 'highlight-indentation-current-column-overlay)
  206. (dolist (hook highlight-indentation-current-column-hooks)
  207. (remove-hook (car hook) (nth 1 hook) (nth 3 hook))))
  208. (when highlight-indentation-current-column-mode ;; ON
  209. (when (not (local-variable-p 'highlight-indentation-offset))
  210. (set (make-local-variable 'highlight-indentation-offset)
  211. (highlight-indentation-guess-offset)))
  212. ;; Setup hooks
  213. (dolist (hook highlight-indentation-current-column-hooks)
  214. (apply 'add-hook hook))
  215. (highlight-indentation-redraw-all-windows 'highlight-indentation-current-column-overlay
  216. 'highlight-indentation-current-column-put-overlays-region)))
  217. (provide 'highlight-indentation)
  218. ;;; highlight-indentation.el ends here