]> code.delx.au - gnu-emacs-elpa/blob - packages/num3-mode/num3-mode.el
* packages/num3-mode/num3-mode.el: Fix compilation warnings.
[gnu-emacs-elpa] / packages / num3-mode / num3-mode.el
1 ;;; num3-mode.el --- highlight groups of digits in long numbers -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 2012, 2014 Free Software Foundation, Inc.
4
5 ;; Author: Felix Lee <felix8a@gmail.com>, Michal Nazarewicz <mina86@mina86.com>
6 ;; Maintainer: Michal Nazarewicz <mina86@mina86.com>
7 ;; Keywords: faces, minor-mode
8 ;; Version: 1.2
9
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24
25 ;; Num3 is a minor mode that makes long numbers more readable by
26 ;; highlighting groups of 3 (customisable) decimal digits or 4 hex
27 ;; digits when font-lock is on. Highlighting alternates between two
28 ;; faces that can be customised.
29
30 ;;; Usage:
31
32 ;; M-x num3-mode toggle for current buffer.
33 ;; M-x global-num3-mode toggle for all buffers.
34 ;;
35 ;; Or add the following to your ~/.emacs file:
36 ;; (load "path/to/num3")
37 ;; (global-num3-mode)
38
39 ;;; Code:
40
41 (defgroup num3 nil
42 "Num3 is a minor mode that makes long numbers more readable by
43 highlighting groups of decimal digits or 4 hex digits when
44 font-lock is on."
45 :group 'text)
46
47 (defcustom num3-group-size 3
48 "Number of digits to group in decimal numbers."
49 :type 'integer)
50
51 (defcustom num3-threshold 5
52 "Number must be at least that long to start highlighting."
53 :type 'integer)
54
55 (defface num3-face-odd
56 '((t))
57 "Face to add for odd groups of digits."
58 :group 'num3)
59
60 (defface num3-face-even
61 '((t :underline t :weight bold :background "#eeeeee"))
62 "Face to add for even groups of digits.
63 The default face uses redundant signaling, because this is in
64 addition to any other font-lock highlighting."
65 :group 'num3)
66
67 ;;; Implementation:
68
69 ;;;###autoload
70 (define-minor-mode num3-mode
71 "Toggle num3 minor mode in the current buffer.
72 Num3 minor mode makes long numbers more readable by highlighting
73 groups of digits when font-lock mode is on.
74
75 If a number is longer than `num3-threshold', the mode will split
76 it into a group of `num3-group-size' (if number is decimal) or
77 4 (if number is hexadecimal) digits. Hexadecimal number is
78 detected as one starting with 0x, 0X or #.
79
80 With decimal numbers, fractions are recognised as well and
81 grouped from the beginning rathar then from end. For instance,
82 with group size of 3, a number \"12345.12345\" will be split into
83 groups as follows: \"12|345.123|45\". Fractions without integer
84 part are also recognised, eg. \".12345\".
85
86 The groups are highlighted alternately using `num3-face-odd' and
87 `num3-face-even' faces. `num3-face-odd' face (which is empty by
88 default) is the one used for the group closest to the decimal point,
89 ie. groups are counted starting with one outwards from the (place
90 where) decimal point (would be) is."
91 nil " num3" nil
92 (if num3-mode
93 (unless (assoc 'num3--matcher font-lock-keywords)
94 (font-lock-add-keywords nil '(num3--matcher) 'append))
95 (font-lock-remove-keywords nil '(num3--matcher)))
96 (if (fboundp 'font-lock-flush) (font-lock-flush)
97 (when font-lock-mode (with-no-warnings (font-lock-fontify-buffer)))))
98
99 ;;;###autoload
100 (define-globalized-minor-mode global-num3-mode num3-mode num3-mode)
101
102 (defconst num3--number-re
103 (concat "[0#][xX]\\([[:xdigit:]]+\\)" ; 1 = hexadecimal
104 "\\|\\(?1:\\b\\(?:[0-9]+[a-fA-F]\\|" ; 1 = hexadecimal
105 "[a-fA-F]+[0-9]\\)[[:xdigit:]]*\\b\\)"
106 "\\|\\([0-9]+\\)" ; 2 = decimal
107 "\\|\\.\\([0-9]+\\)")) ; 3 = fraction
108
109 (defun num3--matcher (lim)
110 "Function used as a font-lock-keywoard handler used in `num3-mode'.
111 Performs fontification of numbers from point to LIM."
112 (save-excursion
113 (while (re-search-forward num3--number-re lim t)
114 (num3--int (match-beginning 1) (match-end 1) 4)
115 (num3--int (match-beginning 2) (match-end 2) num3-group-size)
116 (num3--frac (match-beginning 3) (match-end 3) num3-group-size)))
117 nil)
118
119 (defun num3--int (lo hi n)
120 "Highlight groups of digits in a long number.
121 LO and HI arguments specify the range where the number is
122 located. If the length of that region exceeds `num3-threshold',
123 the function will split it into groups of N digits and fontify
124 tham alternately using `num3-face-odd' and `num3-face-even'
125 faces. Grouping is done from the end, eg. (12)(345)."
126 (when (and lo (>= (- hi lo) num3-threshold))
127 (let (even)
128 (while (< lo hi)
129 (num3--put even (max lo (- hi n)) hi)
130 (setq hi (- hi n) even (not even))))))
131
132 (defun num3--frac (lo hi n)
133 "Highlight groups of digits in a long number.
134 LO and HI arguments specify the range where the number is
135 located. If the length of that region exceeds `num3-threshold',
136 the function will split it into groups of N digits and fontify
137 tham alternately using `num3-face-odd' and `num3-face-even'
138 faces. Grouping is done from the beginning, eg. (123)(45)."
139 (when (and lo (>= (- hi lo) num3-threshold))
140 (let (even)
141 (while (< lo hi)
142 (num3--put even lo (min hi (+ lo n)))
143 (setq lo (+ lo n) even (not even))))))
144
145 (defun num3--put (even lo hi)
146 "Add font lock text property to highlight a single group of digit.
147 Use `num3-face-odd' if EVEN is nil and `num3-face-even' if EVEN is
148 non-nil. The region the face is set to is from LO to HI."
149 (font-lock-append-text-property lo hi 'face
150 (if even 'num3-face-even 'num3-face-odd)))
151
152 (provide 'num3-mode)
153 ;;; num3-mode.el ends here