From 7e9eef0ffd90cd7e39f15b003e4a9770be27b0ce Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Thu, 14 Dec 2017 11:18:51 +0200 Subject: [PATCH] Consolidate 'widen' calls * lisp/progmodes/prog-mode.el (prog-indentation-context): Un-document all elements but the first. (prog-widen): Remove. (http://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00321.html) * doc/lispref/text.texi (Mode-Specific Indent): Update. * lisp/progmodes/ruby-mode.el (ruby-calculate-indent): Don't call widen. * lisp/progmodes/python.el (python-indent-guess-indent-offset) (python-info-current-defun): Replace prog-widen with widen; these functions are not called during indentation. (python-indent-context) (python-indent--calculate-indentation) (python-info-dedenter-opening-block-message) (python-info-line-ends-backslash-p) (python-info-beginning-of-backslash) (python-info-continuation-line-p) (python-info-current-defun): Remove 'widen' calls. * lisp/indent.el (indent-according-to-mode) (indent-for-tab-command, indent-region): Move them here. * lisp/textmodes/mhtml-mode.el (mhtml-indent-line): Bind prog-indentation-context to one-element list. --- doc/lispref/text.texi | 54 ++++++------------------------------ etc/NEWS | 10 +++---- lisp/indent.el | 12 ++++++-- lisp/progmodes/prog-mode.el | 47 ++----------------------------- lisp/progmodes/python.el | 32 ++++++--------------- lisp/progmodes/ruby-mode.el | 1 - lisp/textmodes/mhtml-mode.el | 4 +-- 7 files changed, 35 insertions(+), 125 deletions(-) diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 1e19f75d682..67a303a5994 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -2396,57 +2396,31 @@ text at point (@pxref{Completion in Buffers}). syntax belongs to a different major mode. Examples include @dfn{literate programming} source files that combine documentation and snippets of source code, Yacc/Bison programs that include snippets of -plain C code, etc. To correctly indent the embedded chunks, the major +plain C code, etc. To correctly indent the embedded chunks, the primary mode needs to delegate the indentation to another mode's indentation engine (e.g., call @code{c-indent-defun} for C code or @code{python-indent-line} for Python), while providing it with some -context to guide the indentation. The following facilities support -such multi-mode indentation. +context to guide the indentation. Major modes, for their part, should +avoid calling @code{widen} in their indentation code and obey +@code{prog-first-column}. @defvar prog-indentation-context This variable, when non-@code{nil}, holds the indentation context for the sub-mode's indentation engine provided by the superior major mode. -The value should be a list of the form @code{(@var{first-column} -@w{(@var{start} . @var{end})} @code{prev-chunk})}. The members of the -list have the following meaning: +The value should be a list of the form @code{(@var{first-column} . @var{rest}}. +The members of the list have the following meaning: @table @var @item first-column The column to be used for top-level constructs. This replaces the default value of the top-level column used by the sub-mode, usually zero. -@item start -@itemx end -The region of the code chunk to be indented by the sub-mode. The -value of @var{end} can be @code{nil}, which stands for the value of -@code{point-max}. -@item prev-chunk -If this is non-@code{nil}, it should provide the sub-mode's -indentation engine with a virtual context of the code chunk. Valid -values include: - -@itemize @minus -@item -A string whose contents is the text the sub-mode's indentation engine -should consider to precede the code chunk. The sub-mode's indentation -engine can add text properties to that string, to be reused in -repeated calls with the same string, thus using it as a cache. An -example where this is useful is code chunks that need to be indented -as function bodies, but lack the function's preamble---the string -could then include that missing preamble. -@item -A function. It is expected to be called with the start position of -the current chunk, and should return a cons cell -@w{@code{(@var{prev-start} . @var{prev-end})}} that specifies the -region of the previous code chunk, or @code{nil} if there is no previous -chunk. This is useful in literate-programming sources, where code is -split into chunks, and correct indentation needs to access previous -chunks. -@end itemize +@item rest +This value is currently unused. @end table @end defvar -The following convenience functions should be used by major mode's +The following convenience function should be used by major mode's indentation engine in support of invocations as sub-modes of another major mode. @@ -2457,16 +2431,6 @@ function's value is the column number to use for top-level constructs. When no superior mode is in effect, this function returns zero. @end defun -@defun prog-widen -Call this function instead of @code{widen} to remove any restrictions -imposed by the mode's indentation engine and restore the restrictions -recorded in @code{prog-indentation-context}. This prevents the -indentation engine of a sub-mode from inadvertently operating on text -outside of the chunk it was supposed to indent, and preserves the -restriction imposed by the superior mode. When no superior mode is in -effect, this function just calls @code{widen}. -@end defun - @node Region Indent @subsection Indenting an Entire Region diff --git a/etc/NEWS b/etc/NEWS index 4ccf468693c..eb076c943bc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1107,11 +1107,11 @@ This allows better indentation support in modes that support multiple programming languages in the same buffer, like literate programming environments or ANTLR programs with embedded Python code. -A major mode can provide indentation context for a sub-mode through -the 'prog-indentation-context' variable. To support this, modes that -provide indentation should use 'prog-widen' instead of 'widen' and -'prog-first-column' instead of a literal zero. See the node -"(elisp) Mode-Specific Indent" in the ELisp manual for more details. +A major mode can provide indentation context for a sub-mode. To +support this, modes should use 'prog-first-column' instead of a +literal zero and never call 'widen' in their indentation functions. +See the node "(elisp) Mode-Specific Indent" in the ELisp manual for +more details. ** ERC diff --git a/lisp/indent.el b/lisp/indent.el index d5ba0bd8491..ccf0e99c08b 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -69,6 +69,8 @@ variable is `indent-relative' or `indent-relative-maybe', handle it specially (since those functions are used for tabbing); in that case, indent by aligning to the previous non-blank line." (interactive) + (save-restriction + (widen) (syntax-propertize (line-end-position)) (if (memq indent-line-function '(indent-relative indent-relative-maybe)) @@ -84,7 +86,7 @@ that case, indent by aligning to the previous non-blank line." (indent-line-to column) (save-excursion (indent-line-to column)))) ;; The normal case. - (funcall indent-line-function))) + (funcall indent-line-function)))) (defun indent--default-inside-comment () (unless (or (> (current-column) (current-indentation)) @@ -144,7 +146,9 @@ prefix argument is ignored." (indent--default-inside-comment) (when (or (<= (current-column) (current-indentation)) (not (eq tab-always-indent 'complete))) - (funcall (default-value 'indent-line-function)))) + (save-restriction + (widen) + (funcall (default-value 'indent-line-function))))) (cond ;; If the text was already indented right, try completion. @@ -538,7 +542,9 @@ column to indent to; if it is nil, use one of the three methods above." (forward-line 1))))) ;; Use indent-region-function is available. (indent-region-function - (funcall indent-region-function start end)) + (save-restriction + (widen) + (funcall indent-region-function start end))) ;; Else, use a default implementation that calls indent-line-function on ;; each line. (t (indent-region-line-by-line start end))) diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index f727e458b2b..4efe443fba8 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el @@ -54,7 +54,7 @@ There are languages where part of the code is actually written in a sub language, e.g., a Yacc/Bison or ANTLR grammar also consists -of plain C code. This variable enables the major mode of the +of plain C code. This variable enables the primary mode of the main language to use the indentation engine of the sub-mode for lines in code chunks written in the sub-mode's language. @@ -64,37 +64,13 @@ mode, it should bind this variable to non-nil around the call. The non-nil value should be a list of the form: - (FIRST-COLUMN (START . END) PREVIOUS-CHUNKS) + (FIRST-COLUMN . REST) FIRST-COLUMN is the column the indentation engine of the sub-mode should use for top-level language constructs inside the code chunk (instead of 0). -START and END specify the region of the code chunk. END can be -nil, which stands for the value of `point-max'. The function -`prog-widen' uses this to restore restrictions imposed by the -sub-mode's indentation engine. - -PREVIOUS-CHUNKS, if non-nil, provides the indentation engine of -the sub-mode with the virtual context of the code chunk. Valid -values are: - - - A string containing text which the indentation engine can - consider as standing in front of the code chunk. To cache the - string's calculated syntactic information for repeated calls - with the same string, the sub-mode can add text-properties to - the string. - - A typical use case is for grammars with code chunks which are - to be indented like function bodies -- the string would contain - the corresponding function preamble. - - - A function, to be called with the start position of the current - chunk. It should return either the region of the previous chunk - as (PREV-START . PREV-END), or nil if there is no previous chunk. - - A typical use case are literate programming sources -- the - function would successively return the previous code chunks.") +REST is currently unused.") (defun prog-indent-sexp (&optional defun) "Indent the expression after point. @@ -113,23 +89,6 @@ instead." "Return the indentation column normally used for top-level constructs." (or (car prog-indentation-context) 0)) -(defun prog-widen () - "Remove restrictions (narrowing) from current code chunk or buffer. -This function should be used instead of `widen' in any function used -by the indentation engine to make it respect the value of -`prog-indentation-context'. - -This function (like `widen') is useful inside a -`save-restriction' to make the indentation correctly work when -narrowing is in effect." - (let ((chunk (cadr prog-indentation-context))) - (if chunk - ;; No call to `widen' is necessary here, as narrow-to-region - ;; changes (not just narrows) the existing restrictions - (narrow-to-region (car chunk) (or (cdr chunk) (point-max))) - (widen)))) - - (defvar-local prettify-symbols-alist nil "Alist of symbol prettifications. Each element looks like (SYMBOL . CHARACTER), where the symbol diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index d4226e5ce7b..b8926529d1e 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -287,10 +287,6 @@ ;;; 24.x Compat -(unless (fboundp 'prog-widen) - (defun prog-widen () - (widen))) - (unless (fboundp 'prog-first-column) (defun prog-first-column () 0)) @@ -785,7 +781,7 @@ work on `python-indent-calculate-indentation' instead." (interactive) (save-excursion (save-restriction - (prog-widen) + (widen) (goto-char (point-min)) (let ((block-end)) (while (and (not block-end) @@ -883,8 +879,6 @@ keyword :at-dedenter-block-start - Point is on a line starting a dedenter block. - START is the position where the dedenter block starts." - (save-restriction - (prog-widen) (let ((ppss (save-excursion (beginning-of-line) (syntax-ppss)))) @@ -1022,7 +1016,7 @@ keyword (looking-at (python-rx block-ender))) :after-block-end) (t :after-line)) - (point))))))))) + (point)))))))) (defun python-indent--calculate-indentation () "Internal implementation of `python-indent-calculate-indentation'. @@ -1030,8 +1024,6 @@ May return an integer for the maximum possible indentation at current context or a list of integers. The latter case is only happening for :at-dedenter-block-start context since the possibilities can be narrowed to specific indentation points." - (save-restriction - (prog-widen) (save-excursion (pcase (python-indent-context) (`(:no-indent . ,_) (prog-first-column)) ; usually 0 @@ -1081,7 +1073,7 @@ possibilities can be narrowed to specific indentation points." (`(,(or :inside-paren-newline-start-from-block) . ,start) ;; Add two indentation levels to make the suite stand out. (goto-char start) - (+ (current-indentation) (* python-indent-offset 2))))))) + (+ (current-indentation) (* python-indent-offset 2)))))) (defun python-indent--calculate-levels (indentation) "Calculate levels list given INDENTATION. @@ -4590,7 +4582,7 @@ Optional argument INCLUDE-TYPE indicates to include the type of the defun. This function can be used as the value of `add-log-current-defun-function' since it returns nil if point is not inside a defun." (save-restriction - (prog-widen) + (widen) (save-excursion (end-of-line 1) (let ((names) @@ -4788,12 +4780,10 @@ likely an invalid python file." "Message the first line of the block the current statement closes." (let ((point (python-info-dedenter-opening-block-position))) (when point - (save-restriction - (prog-widen) (message "Closes %s" (save-excursion (goto-char point) (buffer-substring - (point) (line-end-position)))))))) + (point) (line-end-position))))))) (defun python-info-dedenter-statement-p () "Return point if current statement is a dedenter. @@ -4809,8 +4799,6 @@ statement." "Return non-nil if current line ends with backslash. With optional argument LINE-NUMBER, check that line instead." (save-excursion - (save-restriction - (prog-widen) (when line-number (python-util-goto-line line-number)) (while (and (not (eobp)) @@ -4819,14 +4807,12 @@ With optional argument LINE-NUMBER, check that line instead." (not (equal (char-before (point)) ?\\))) (forward-line 1)) (when (equal (char-before) ?\\) - (point-marker))))) + (point-marker)))) (defun python-info-beginning-of-backslash (&optional line-number) "Return the point where the backslashed line start. Optional argument LINE-NUMBER forces the line number to check against." (save-excursion - (save-restriction - (prog-widen) (when line-number (python-util-goto-line line-number)) (when (python-info-line-ends-backslash-p) @@ -4835,15 +4821,13 @@ Optional argument LINE-NUMBER forces the line number to check against." (python-syntax-context 'paren)) (forward-line -1)) (back-to-indentation) - (point-marker))))) + (point-marker)))) (defun python-info-continuation-line-p () "Check if current line is continuation of another. When current line is continuation of another return the point where the continued line ends." (save-excursion - (save-restriction - (prog-widen) (let* ((context-type (progn (back-to-indentation) (python-syntax-context-type))) @@ -4869,7 +4853,7 @@ where the continued line ends." (python-util-forward-comment -1) (when (and (equal (1- line-start) (line-number-at-pos)) (python-info-line-ends-backslash-p)) - (point-marker)))))))) + (point-marker))))))) (defun python-info-block-continuation-line-p () "Return non-nil if current line is a continuation of a block." diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index dc1b0f8e2da..7c101143347 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -1364,7 +1364,6 @@ delimiter." "\\)\\>"))) (eq (ruby-deep-indent-paren-p t) 'space) (not (bobp))) - (widen) (goto-char (or begin parse-start)) (skip-syntax-forward " ") (current-column)) diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el index 09da155f487..79c1125ff62 100644 --- a/lisp/textmodes/mhtml-mode.el +++ b/lisp/textmodes/mhtml-mode.el @@ -341,9 +341,7 @@ This is used by `mhtml--pre-command'.") ((eq mhtml-tag-relative-indent 'ignore) (setq base-indent 0))) (narrow-to-region region-start (point-max)) - (let ((prog-indentation-context (list base-indent - (cons (point-min) nil) - nil))) + (let ((prog-indentation-context (list base-indent))) (mhtml--with-locals submode ;; indent-line-function was rebound by ;; mhtml--with-locals. -- 2.39.2