mirror of https://github.com/Chizi123/.emacs.d.git

Chizi123
2018-11-21 7074318d7ab58aca124f590c42fd820e8eb258a5
commit | author | age
5cb5f7 1 ;;; diff-hl-margin.el --- Highlight buffer changes on margins -*- lexical-binding: t -*-
C 2
3 ;; Copyright (C) 2012-2017  Free Software Foundation, Inc.
4
5 ;; This file is part of GNU Emacs.
6
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.
11
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.
16
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/>.
19
20 ;;; Commentary:
21
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'.
24 ;;
25 ;; Compared to the default behavior, this makes `diff-hl-mode'
26 ;; indicators show up even when Emacs is running in a terminal.
27 ;;
28 ;; On the flip side, the indicators look simpler, and they are
29 ;; incompatible with `linum-mode' or any other mode that uses the
30 ;; margin.
31 ;;
32 ;; You might want to enable it conditionally in your init file
33 ;; depending on whether Emacs is running in graphical mode:
34 ;;
35 ;; (unless (window-system) (diff-hl-margin-mode))
36
37 (require 'cl-lib)
38 (require 'diff-hl)
39 (require 'diff-hl-dired)
40
41 (defvar diff-hl-margin-old-highlight-function nil)
42
43 (defgroup diff-hl-margin nil
44   "Highlight buffer changes on margin"
45   :group 'diff-hl)
46
47 (defface diff-hl-margin-insert
48   '((default :inherit diff-hl-insert))
49   "Face used to highlight inserted lines on the margin.")
50
51 (defface diff-hl-margin-delete
52   '((default :inherit diff-hl-delete))
53   "Face used to highlight deleted lines on the margin.")
54
55 (defface diff-hl-margin-change
56   '((default :inherit diff-hl-change))
57   "Face used to highlight changed lines on the margin.")
58
59 (defface diff-hl-margin-ignored
60   '((default :inherit dired-ignored))
61   "Face used to highlight changed lines on the margin.")
62
63 (defface diff-hl-margin-unknown
64   '((default :inherit dired-ignored))
65   "Face used to highlight changed lines on the margin.")
66
67 (defcustom diff-hl-margin-symbols-alist
68   '((insert . "+") (delete . "-") (change . "!")
69     (unknown . "?") (ignored . "i"))
70   "Associative list from symbols to strings."
71   :type '(alist :key-type symbol
72                 :value-type string
73                 :options (insert delete change unknown ignored))
74   :set (lambda (symbol value)
75          (defvar diff-hl-margin-spec-cache)
76          (set-default symbol value)
77          (setq diff-hl-margin-spec-cache nil)))
78
79 ;;;###autoload
80 (define-minor-mode diff-hl-margin-mode
81   "Toggle displaying `diff-hl-mode' highlights on the margin."
82   :lighter "" :global t
83   (if diff-hl-margin-mode
84       (progn
85         (add-hook 'diff-hl-mode-on-hook 'diff-hl-margin-minor-mode)
86         (add-hook 'diff-hl-mode-off-hook 'diff-hl-margin-minor-mode-off)
87         (add-hook 'diff-hl-dired-mode-on-hook 'diff-hl-margin-minor-mode)
88         (add-hook 'diff-hl-dired-mode-off-hook 'diff-hl-margin-minor-mode-off))
89     (remove-hook 'diff-hl-mode-on-hook 'diff-hl-margin-minor-mode)
90     (remove-hook 'diff-hl-mode-off-hook 'diff-hl-margin-minor-mode-off)
91     (remove-hook 'diff-hl-dired-mode-on-hook 'diff-hl-margin-minor-mode)
92     (remove-hook 'diff-hl-dired-mode-off-hook 'diff-hl-margin-minor-mode-off))
93   (dolist (buf (buffer-list))
94     (with-current-buffer buf
95       (cond
96        (diff-hl-mode
97         (diff-hl-margin-minor-mode (if diff-hl-margin-mode 1 -1))
98         (diff-hl-update))
99        (diff-hl-dired-mode
100         (diff-hl-margin-minor-mode (if diff-hl-margin-mode 1 -1))
101         (diff-hl-dired-update))))))
102
103 (define-minor-mode diff-hl-margin-minor-mode
104   "Toggle displaying `diff-hl-mode' highlights on the margin locally.
105 You probably shouldn't use this function directly."
106   :lighter ""
107   (let ((width-var (intern (format "%s-margin-width" diff-hl-side))))
108     (if diff-hl-margin-minor-mode
109         (progn
110           (set (make-local-variable 'diff-hl-margin-old-highlight-function)
111                diff-hl-highlight-function)
112           (set (make-local-variable 'diff-hl-highlight-function)
113                'diff-hl-highlight-on-margin)
114           (set width-var 1))
115       (setq diff-hl-highlight-function diff-hl-margin-old-highlight-function
116             diff-hl-margin-old-highlight-function nil)
117       (set width-var 0)))
118   (dolist (win (get-buffer-window-list))
119     (set-window-buffer win (current-buffer))))
120
121 (define-obsolete-variable-alias 'diff-hl-margin-side 'diff-hl-side "1.7.1")
122
123 (defun diff-hl-margin-minor-mode-off ()
124   (diff-hl-margin-minor-mode -1))
125
126 (defvar diff-hl-margin-spec-cache nil)
127
128 (defun diff-hl-margin-spec-cache ()
129   (or diff-hl-margin-spec-cache
130       (setq diff-hl-margin-spec-cache
131             (diff-hl-margin-build-spec-cache))))
132
133 (defun diff-hl-margin-build-spec-cache ()
134   (cl-loop for (type . char) in diff-hl-margin-symbols-alist
135            nconc
136            (cl-loop for side in '(left right)
137                     collect
138                     (cons
139                      (cons type side)
140                      (propertize
141                       " " 'display
142                       `((margin ,(intern (format "%s-margin" side)))
143                         ,(propertize char 'face
144                                      (intern (format "diff-hl-margin-%s" type)))))))))
145
146 (defun diff-hl-highlight-on-margin (ovl type _shape)
147   (let ((spec (cdr (assoc (cons type diff-hl-side)
148                           (diff-hl-margin-spec-cache)))))
149     (overlay-put ovl 'before-string spec)))
150
151 (provide 'diff-hl-margin)
152
153 ;;; diff-hl-margin.el ends here