Prefer directed to neutral quotes
[emacs.git] / lisp / progmodes / prog-mode.el
blob8f50887113e589287beb40f1b4c662aa0c0cc40f
1 ;;; prog-mode.el --- Generic major mode for programming -*- lexical-binding: t -*-
3 ;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
5 ;; Maintainer: emacs-devel@gnu.org
6 ;; Keywords: internal
7 ;; Package: emacs
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24 ;;; Commentary:
26 ;; This major mode is mostly intended as a parent of other programming
27 ;; modes. All major modes for programming languages should derive from this
28 ;; mode so that users can put generic customization on prog-mode-hook.
30 ;;; Code:
32 (eval-when-compile (require 'cl-lib))
34 (defgroup prog-mode nil
35 "Generic programming mode, from which others derive."
36 :group 'languages)
38 (defcustom prog-mode-hook nil
39 "Normal hook run when entering programming modes."
40 :type 'hook
41 :options '(flyspell-prog-mode abbrev-mode flymake-mode linum-mode
42 prettify-symbols-mode)
43 :group 'prog-mode)
45 (defvar prog-mode-map
46 (let ((map (make-sparse-keymap)))
47 (define-key map [?\C-\M-q] 'prog-indent-sexp)
48 map)
49 "Keymap used for programming modes.")
51 (defvar prog-indentation-context nil
52 "Non-nil while indenting embedded code chunks.
53 There are languages where part of the code is actually written in
54 a sub language, e.g., a Yacc/Bison or ANTLR grammar also consists
55 of plain C code. This variable enables the major mode of the
56 main language to use the indentation engine of the sub mode for
57 lines in code chunks written in the sub language.
59 When a major mode of such a main language decides to delegate the
60 indentation of a line/region to the indentation engine of the sub
61 mode, it is supposed to bind this variable to non-nil around the call.
63 The non-nil value looks as follows
64 \(FIRST-COLUMN (START . END) PREVIOUS-CHUNKS)
66 FIRST-COLUMN is the column the indentation engine of the sub mode
67 should usually choose for top-level language constructs inside
68 the code chunk (instead of 0).
70 START to END is the region of the code chunk. See function
71 `prog-widen' for additional info.
73 PREVIOUS-CHUNKS, if non-nil, provides the indentation engine of
74 the sub mode with the virtual context of the code chunk. Valid
75 values are:
77 - A string containing code which the indentation engine can
78 consider as standing in front of the code chunk. To cache the
79 string's calculated syntactic information for repeated calls
80 with the same string, it is valid and expected for the inner
81 mode to add text-properties to the string.
83 A typical use case is for grammars with code chunks which are
84 to be indented like function bodies - the string would contain
85 a corresponding function header.
87 - A function called with the start position of the current
88 chunk. It will return either the region of the previous chunk
89 as \(PREV-START . PREV-END) or nil if there is no further
90 previous chunk.
92 A typical use case are literate programming sources - the
93 function would successively return the code chunks of the
94 previous macro definitions for the same name.")
96 (defun prog-indent-sexp (&optional defun)
97 "Indent the expression after point.
98 When interactively called with prefix, indent the enclosing defun
99 instead."
100 (interactive "P")
101 (save-excursion
102 (when defun
103 (end-of-line)
104 (beginning-of-defun))
105 (let ((start (point))
106 (end (progn (forward-sexp 1) (point))))
107 (indent-region start end nil))))
109 (defun prog-first-column ()
110 "Return the indentation column normally used for top-level constructs."
111 (or (car prog-indentation-context) 0))
113 (defun prog-widen ()
114 "Remove restrictions (narrowing) from current code chunk or buffer.
115 This function can be used instead of `widen' in any function used
116 by the indentation engine to make it respect the value
117 `prog-indentation-context'.
119 This function (like `widen') is useful inside a
120 `save-restriction' to make the indentation correctly work when
121 narrowing is in effect."
122 (let ((chunk (cadr prog-indentation-context)))
123 (if chunk
124 ;; no widen necessary here, as narrow-to-region changes (not
125 ;; just narrows) existing restrictions
126 (narrow-to-region (car chunk) (or (cdr chunk) (point-max)))
127 (widen))))
130 (defvar-local prettify-symbols-alist nil
131 "Alist of symbol prettifications.
132 Each element looks like (SYMBOL . CHARACTER), where the symbol
133 matching SYMBOL (a string, not a regexp) will be shown as
134 CHARACTER instead.")
136 (defun prettify-symbols-default-compose-p (start end _match)
137 "Return true iff the symbol MATCH should be composed.
138 The symbol starts at position START and ends at position END.
139 This is default `prettify-symbols-compose-predicate' which is
140 suitable for most programming languages such as C or Lisp."
141 ;; Check that the chars should really be composed into a symbol.
142 (let* ((syntaxes-beg (if (memq (char-syntax (char-after start)) '(?w ?_))
143 '(?w ?_) '(?. ?\\)))
144 (syntaxes-end (if (memq (char-syntax (char-before end)) '(?w ?_))
145 '(?w ?_) '(?. ?\\))))
146 (not (or (memq (char-syntax (or (char-before start) ?\s)) syntaxes-beg)
147 (memq (char-syntax (or (char-after end) ?\s)) syntaxes-end)
148 (nth 8 (syntax-ppss))))))
150 (defvar-local prettify-symbols-compose-predicate
151 #'prettify-symbols-default-compose-p
152 "A predicate deciding if the currently matched symbol is to be composed.
153 The matched symbol is the car of one entry in `prettify-symbols-alist'.
154 The predicate receives the match's start and end position as well
155 as the match-string as arguments.")
157 (defun prettify-symbols--compose-symbol (alist)
158 "Compose a sequence of characters into a symbol.
159 Regexp match data 0 points to the chars."
160 ;; Check that the chars should really be composed into a symbol.
161 (let ((start (match-beginning 0))
162 (end (match-end 0))
163 (match (match-string 0)))
164 (if (funcall prettify-symbols-compose-predicate start end match)
165 ;; That's a symbol alright, so add the composition.
166 (compose-region start end (cdr (assoc match alist)))
167 ;; No composition for you. Let's actually remove any
168 ;; composition we may have added earlier and which is now
169 ;; incorrect.
170 (remove-text-properties start end '(composition))))
171 ;; Return nil because we're not adding any face property.
172 nil)
174 (defun prettify-symbols--make-keywords ()
175 (if prettify-symbols-alist
176 `((,(regexp-opt (mapcar 'car prettify-symbols-alist) t)
177 (0 (prettify-symbols--compose-symbol ',prettify-symbols-alist))))
178 nil))
180 (defvar-local prettify-symbols--keywords nil)
182 ;;;###autoload
183 (define-minor-mode prettify-symbols-mode
184 "Toggle Prettify Symbols mode.
185 With a prefix argument ARG, enable Prettify Symbols mode if ARG is
186 positive, and disable it otherwise. If called from Lisp, enable
187 the mode if ARG is omitted or nil.
189 When Prettify Symbols mode and font-locking are enabled, symbols are
190 prettified (displayed as composed characters) according to the rules
191 in `prettify-symbols-alist' (which see), which are locally defined
192 by major modes supporting prettifying. To add further customizations
193 for a given major mode, you can modify `prettify-symbols-alist' thus:
195 (add-hook \\='emacs-lisp-mode-hook
196 (lambda ()
197 (push \\='(\"<=\" . ?≤) prettify-symbols-alist)))
199 You can enable this mode locally in desired buffers, or use
200 `global-prettify-symbols-mode' to enable it for all modes that
201 support it."
202 :init-value nil
203 (if prettify-symbols-mode
204 ;; Turn on
205 (when (setq prettify-symbols--keywords (prettify-symbols--make-keywords))
206 (font-lock-add-keywords nil prettify-symbols--keywords)
207 (setq-local font-lock-extra-managed-props
208 (cons 'composition font-lock-extra-managed-props))
209 (font-lock-flush))
210 ;; Turn off
211 (when prettify-symbols--keywords
212 (font-lock-remove-keywords nil prettify-symbols--keywords)
213 (setq prettify-symbols--keywords nil))
214 (when (memq 'composition font-lock-extra-managed-props)
215 (setq font-lock-extra-managed-props (delq 'composition
216 font-lock-extra-managed-props))
217 (with-silent-modifications
218 (remove-text-properties (point-min) (point-max) '(composition nil))))))
220 (defun turn-on-prettify-symbols-mode ()
221 (when (and (not prettify-symbols-mode)
222 (local-variable-p 'prettify-symbols-alist))
223 (prettify-symbols-mode 1)))
225 ;;;###autoload
226 (define-globalized-minor-mode global-prettify-symbols-mode
227 prettify-symbols-mode turn-on-prettify-symbols-mode)
229 ;;;###autoload
230 (define-derived-mode prog-mode fundamental-mode "Prog"
231 "Major mode for editing programming language source code."
232 (setq-local require-final-newline mode-require-final-newline)
233 (setq-local parse-sexp-ignore-comments t)
234 ;; Any programming language is always written left to right.
235 (setq bidi-paragraph-direction 'left-to-right))
237 (provide 'prog-mode)
239 ;;; prog-mode.el ends here