1 ;;; diff-hl-margin.el --- Highlight buffer changes on margins -*- lexical-binding: t -*-
3 ;; Copyright (C) 2012-2015 Free Software Foundation, Inc.
5 ;; This file is part of GNU Emacs.
7 ;; GNU Emacs is free software: you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; GNU Emacs is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22 ;; This is a global mode, it modifies `diff-hl-mode' to use the margin
23 ;; instead of the fringe. To toggle, type `M-x diff-hl-margin-mode'.
25 ;; Compared to the default behavior, this makes `diff-hl-mode'
26 ;; indicators show up even when Emacs is running in a terminal.
28 ;; On the flip side, the indicators look simpler, and they are
29 ;; incompatible with `linum-mode' or any other mode that uses the
32 ;; You might want to enable it conditionally in your init file
33 ;; depending on whether Emacs is running in graphical mode:
35 ;; (unless (window-system) (diff-hl-margin-mode))
39 (require 'diff-hl-dired)
41 (defvar diff-hl-margin-old-highlight-function nil)
43 (defgroup diff-hl-margin nil
44 "Highlight buffer changes on margin"
48 (define-minor-mode diff-hl-margin-mode
49 "Toggle displaying `diff-hl-mode' highlights on the margin."
51 (if diff-hl-margin-mode
53 (add-hook 'diff-hl-mode-on-hook 'diff-hl-margin-minor-mode)
54 (add-hook 'diff-hl-mode-off-hook 'diff-hl-margin-minor-mode-off)
55 (add-hook 'diff-hl-dired-mode-on-hook 'diff-hl-margin-minor-mode)
56 (add-hook 'diff-hl-dired-mode-off-hook 'diff-hl-margin-minor-mode-off))
57 (remove-hook 'diff-hl-mode-on-hook 'diff-hl-margin-minor-mode)
58 (remove-hook 'diff-hl-mode-off-hook 'diff-hl-margin-minor-mode-off)
59 (remove-hook 'diff-hl-dired-mode-on-hook 'diff-hl-margin-minor-mode)
60 (remove-hook 'diff-hl-dired-mode-off-hook 'diff-hl-margin-minor-mode-off))
61 (dolist (buf (buffer-list))
62 (with-current-buffer buf
65 (diff-hl-margin-minor-mode (if diff-hl-margin-mode 1 -1))
68 (diff-hl-margin-minor-mode (if diff-hl-margin-mode 1 -1))
69 (diff-hl-dired-update))))))
71 (define-minor-mode diff-hl-margin-minor-mode
72 "Toggle displaying `diff-hl-mode' highlights on the margin locally.
73 You probably shouldn't use this function directly."
75 (let ((width-var (intern (format "%s-margin-width" diff-hl-side))))
76 (if diff-hl-margin-minor-mode
78 (set (make-local-variable 'diff-hl-margin-old-highlight-function)
79 diff-hl-highlight-function)
80 (set (make-local-variable 'diff-hl-highlight-function)
81 'diff-hl-highlight-on-margin)
83 (setq diff-hl-highlight-function diff-hl-margin-old-highlight-function
84 diff-hl-margin-old-highlight-function nil)
86 (dolist (win (get-buffer-window-list))
87 (set-window-buffer win (current-buffer))))
89 (define-obsolete-variable-alias 'diff-hl-margin-side 'diff-hl-side "1.7.1")
91 (defun diff-hl-margin-minor-mode-off ()
92 (diff-hl-margin-minor-mode -1))
94 (defvar diff-hl-margin-spec-cache
95 (cl-loop for (type . char) in '((insert . "+") (delete . "-")
96 (change . "!") (unknown . "?")
99 (cl-loop for side in '(left right)
101 (cons (cons type side)
104 `((margin ,(intern (format "%s-margin" side)))
105 ,(propertize char 'face
106 (intern (format "diff-hl-%s" type)))))))))
108 (defun diff-hl-highlight-on-margin (ovl type _shape)
109 (let ((spec (cdr (assoc (cons type diff-hl-side)
110 diff-hl-margin-spec-cache))))
111 (overlay-put ovl 'before-string spec)))
113 (provide 'diff-hl-margin)
115 ;;; diff-hl-margin.el ends here