Merge branch 'widen-less' into emacs-26

This commit is contained in:
Dmitry Gutov 2017-12-21 00:34:07 +02:00
commit aca827b0d0
7 changed files with 40 additions and 127 deletions

View file

@ -2396,57 +2396,31 @@ text at point (@pxref{Completion in Buffers}).
syntax belongs to a different major mode. Examples include syntax belongs to a different major mode. Examples include
@dfn{literate programming} source files that combine documentation and @dfn{literate programming} source files that combine documentation and
snippets of source code, Yacc/Bison programs that include snippets of snippets of source code, Yacc/Bison programs that include snippets of
plain C code, etc. To correctly indent the embedded chunks, the major Python or JS code, etc. To correctly indent the embedded chunks, the primary
mode needs to delegate the indentation to another mode's indentation mode needs to delegate the indentation to another mode's indentation
engine (e.g., call @code{c-indent-defun} for C code or engine (e.g., call @code{js-indent-line} for JS code or
@code{python-indent-line} for Python), while providing it with some @code{python-indent-line} for Python), while providing it with some
context to guide the indentation. The following facilities support context to guide the indentation. Major modes, for their part, should
such multi-mode indentation. avoid calling @code{widen} in their indentation code and obey
@code{prog-first-column}.
@defvar prog-indentation-context @defvar prog-indentation-context
This variable, when non-@code{nil}, holds the indentation context for This variable, when non-@code{nil}, holds the indentation context for
the sub-mode's indentation engine provided by the superior major mode. 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} The value should be a list of the form @code{(@var{first-column} . @var{rest}}.
@w{(@var{start} . @var{end})} @code{prev-chunk})}. The members of the The members of the list have the following meaning:
list have the following meaning:
@table @var @table @var
@item first-column @item first-column
The column to be used for top-level constructs. This replaces the 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 default value of the top-level column used by the sub-mode, usually
zero. zero.
@item start @item rest
@itemx end This value is currently unused.
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
@end table @end table
@end defvar @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 indentation engine in support of invocations as sub-modes of another
major mode. 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. When no superior mode is in effect, this function returns zero.
@end defun @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 @node Region Indent
@subsection Indenting an Entire Region @subsection Indenting an Entire Region

View file

@ -1119,11 +1119,11 @@ This allows better indentation support in modes that support multiple
programming languages in the same buffer, like literate programming programming languages in the same buffer, like literate programming
environments or ANTLR programs with embedded Python code. environments or ANTLR programs with embedded Python code.
A major mode can provide indentation context for a sub-mode through A major mode can provide indentation context for a sub-mode. To
the 'prog-indentation-context' variable. To support this, modes that support this, modes should use 'prog-first-column' instead of a
provide indentation should use 'prog-widen' instead of 'widen' and literal zero and avoid calling 'widen' in their indentation functions.
'prog-first-column' instead of a literal zero. See the node See the node "(elisp) Mode-Specific Indent" in the ELisp manual for
"(elisp) Mode-Specific Indent" in the ELisp manual for more details. more details.
** ERC ** ERC

View file

@ -69,6 +69,8 @@ variable is `indent-relative' or `indent-relative-maybe', handle
it specially (since those functions are used for tabbing); in it specially (since those functions are used for tabbing); in
that case, indent by aligning to the previous non-blank line." that case, indent by aligning to the previous non-blank line."
(interactive) (interactive)
(save-restriction
(widen)
(syntax-propertize (line-end-position)) (syntax-propertize (line-end-position))
(if (memq indent-line-function (if (memq indent-line-function
'(indent-relative indent-relative-maybe)) '(indent-relative indent-relative-maybe))
@ -84,7 +86,7 @@ that case, indent by aligning to the previous non-blank line."
(indent-line-to column) (indent-line-to column)
(save-excursion (indent-line-to column)))) (save-excursion (indent-line-to column))))
;; The normal case. ;; The normal case.
(funcall indent-line-function))) (funcall indent-line-function))))
(defun indent--default-inside-comment () (defun indent--default-inside-comment ()
(unless (or (> (current-column) (current-indentation)) (unless (or (> (current-column) (current-indentation))
@ -140,11 +142,11 @@ prefix argument is ignored."
(old-indent (current-indentation))) (old-indent (current-indentation)))
;; Indent the line. ;; Indent the line.
(or (not (eq (funcall indent-line-function) 'noindent)) (or (not (eq (indent--funcall-widened indent-line-function) 'noindent))
(indent--default-inside-comment) (indent--default-inside-comment)
(when (or (<= (current-column) (current-indentation)) (when (or (<= (current-column) (current-indentation))
(not (eq tab-always-indent 'complete))) (not (eq tab-always-indent 'complete)))
(funcall (default-value 'indent-line-function)))) (indent--funcall-widened (default-value 'indent-line-function))))
(cond (cond
;; If the text was already indented right, try completion. ;; If the text was already indented right, try completion.
@ -166,6 +168,11 @@ prefix argument is ignored."
(< (point) end-marker)) (< (point) end-marker))
(indent-rigidly (point) end-marker indentation-change)))))))))) (indent-rigidly (point) end-marker indentation-change))))))))))
(defun indent--funcall-widened (func)
(save-restriction
(widen)
(funcall func)))
(defun insert-tab (&optional arg) (defun insert-tab (&optional arg)
(let ((count (prefix-numeric-value arg))) (let ((count (prefix-numeric-value arg)))
(if (and abbrev-mode (if (and abbrev-mode
@ -538,7 +545,9 @@ column to indent to; if it is nil, use one of the three methods above."
(forward-line 1))))) (forward-line 1)))))
;; Use indent-region-function is available. ;; Use indent-region-function is available.
(indent-region-function (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 ;; Else, use a default implementation that calls indent-line-function on
;; each line. ;; each line.
(t (indent-region-line-by-line start end))) (t (indent-region-line-by-line start end)))

View file

@ -54,7 +54,7 @@
There are languages where part of the code is actually written in 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 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 main language to use the indentation engine of the sub-mode for
lines in code chunks written in the sub-mode's language. 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: 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 FIRST-COLUMN is the column the indentation engine of the sub-mode
should use for top-level language constructs inside the code should use for top-level language constructs inside the code
chunk (instead of 0). chunk (instead of 0).
START and END specify the region of the code chunk. END can be REST is currently unused.")
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.")
(defun prog-indent-sexp (&optional defun) (defun prog-indent-sexp (&optional defun)
"Indent the expression after point. "Indent the expression after point.
@ -113,23 +89,6 @@ instead."
"Return the indentation column normally used for top-level constructs." "Return the indentation column normally used for top-level constructs."
(or (car prog-indentation-context) 0)) (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 (defvar-local prettify-symbols-alist nil
"Alist of symbol prettifications. "Alist of symbol prettifications.
Each element looks like (SYMBOL . CHARACTER), where the symbol Each element looks like (SYMBOL . CHARACTER), where the symbol

View file

@ -287,10 +287,6 @@
;;; 24.x Compat ;;; 24.x Compat
(unless (fboundp 'prog-widen)
(defun prog-widen ()
(widen)))
(unless (fboundp 'prog-first-column) (unless (fboundp 'prog-first-column)
(defun prog-first-column () (defun prog-first-column ()
0)) 0))
@ -785,7 +781,7 @@ work on `python-indent-calculate-indentation' instead."
(interactive) (interactive)
(save-excursion (save-excursion
(save-restriction (save-restriction
(prog-widen) (widen)
(goto-char (point-min)) (goto-char (point-min))
(let ((block-end)) (let ((block-end))
(while (and (not block-end) (while (and (not block-end)
@ -883,8 +879,6 @@ keyword
:at-dedenter-block-start :at-dedenter-block-start
- Point is on a line starting a dedenter block. - Point is on a line starting a dedenter block.
- START is the position where the dedenter block starts." - START is the position where the dedenter block starts."
(save-restriction
(prog-widen)
(let ((ppss (save-excursion (let ((ppss (save-excursion
(beginning-of-line) (beginning-of-line)
(syntax-ppss)))) (syntax-ppss))))
@ -1022,7 +1016,7 @@ keyword
(looking-at (python-rx block-ender))) (looking-at (python-rx block-ender)))
:after-block-end) :after-block-end)
(t :after-line)) (t :after-line))
(point))))))))) (point))))))))
(defun python-indent--calculate-indentation () (defun python-indent--calculate-indentation ()
"Internal implementation of `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 current context or a list of integers. The latter case is only
happening for :at-dedenter-block-start context since the happening for :at-dedenter-block-start context since the
possibilities can be narrowed to specific indentation points." possibilities can be narrowed to specific indentation points."
(save-restriction
(prog-widen)
(save-excursion (save-excursion
(pcase (python-indent-context) (pcase (python-indent-context)
(`(:no-indent . ,_) (prog-first-column)) ; usually 0 (`(: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) (`(,(or :inside-paren-newline-start-from-block) . ,start)
;; Add two indentation levels to make the suite stand out. ;; Add two indentation levels to make the suite stand out.
(goto-char start) (goto-char start)
(+ (current-indentation) (* python-indent-offset 2))))))) (+ (current-indentation) (* python-indent-offset 2))))))
(defun python-indent--calculate-levels (indentation) (defun python-indent--calculate-levels (indentation)
"Calculate levels list given INDENTATION. "Calculate levels list given INDENTATION.
@ -4593,7 +4585,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' 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." since it returns nil if point is not inside a defun."
(save-restriction (save-restriction
(prog-widen) (widen)
(save-excursion (save-excursion
(end-of-line 1) (end-of-line 1)
(let ((names) (let ((names)
@ -4791,12 +4783,10 @@ likely an invalid python file."
"Message the first line of the block the current statement closes." "Message the first line of the block the current statement closes."
(let ((point (python-info-dedenter-opening-block-position))) (let ((point (python-info-dedenter-opening-block-position)))
(when point (when point
(save-restriction
(prog-widen)
(message "Closes %s" (save-excursion (message "Closes %s" (save-excursion
(goto-char point) (goto-char point)
(buffer-substring (buffer-substring
(point) (line-end-position)))))))) (point) (line-end-position)))))))
(defun python-info-dedenter-statement-p () (defun python-info-dedenter-statement-p ()
"Return point if current statement is a dedenter. "Return point if current statement is a dedenter.
@ -4812,8 +4802,6 @@ statement."
"Return non-nil if current line ends with backslash. "Return non-nil if current line ends with backslash.
With optional argument LINE-NUMBER, check that line instead." With optional argument LINE-NUMBER, check that line instead."
(save-excursion (save-excursion
(save-restriction
(prog-widen)
(when line-number (when line-number
(python-util-goto-line line-number)) (python-util-goto-line line-number))
(while (and (not (eobp)) (while (and (not (eobp))
@ -4822,14 +4810,12 @@ With optional argument LINE-NUMBER, check that line instead."
(not (equal (char-before (point)) ?\\))) (not (equal (char-before (point)) ?\\)))
(forward-line 1)) (forward-line 1))
(when (equal (char-before) ?\\) (when (equal (char-before) ?\\)
(point-marker))))) (point-marker))))
(defun python-info-beginning-of-backslash (&optional line-number) (defun python-info-beginning-of-backslash (&optional line-number)
"Return the point where the backslashed line starts. "Return the point where the backslashed line starts.
Optional argument LINE-NUMBER forces the line number to check against." Optional argument LINE-NUMBER forces the line number to check against."
(save-excursion (save-excursion
(save-restriction
(prog-widen)
(when line-number (when line-number
(python-util-goto-line line-number)) (python-util-goto-line line-number))
(when (python-info-line-ends-backslash-p) (when (python-info-line-ends-backslash-p)
@ -4838,15 +4824,13 @@ Optional argument LINE-NUMBER forces the line number to check against."
(python-syntax-context 'paren)) (python-syntax-context 'paren))
(forward-line -1)) (forward-line -1))
(back-to-indentation) (back-to-indentation)
(point-marker))))) (point-marker))))
(defun python-info-continuation-line-p () (defun python-info-continuation-line-p ()
"Check if current line is continuation of another. "Check if current line is continuation of another.
When current line is continuation of another return the point When current line is continuation of another return the point
where the continued line ends." where the continued line ends."
(save-excursion (save-excursion
(save-restriction
(prog-widen)
(let* ((context-type (progn (let* ((context-type (progn
(back-to-indentation) (back-to-indentation)
(python-syntax-context-type))) (python-syntax-context-type)))
@ -4872,7 +4856,7 @@ where the continued line ends."
(python-util-forward-comment -1) (python-util-forward-comment -1)
(when (and (equal (1- line-start) (line-number-at-pos)) (when (and (equal (1- line-start) (line-number-at-pos))
(python-info-line-ends-backslash-p)) (python-info-line-ends-backslash-p))
(point-marker)))))))) (point-marker)))))))
(defun python-info-block-continuation-line-p () (defun python-info-block-continuation-line-p ()
"Return non-nil if current line is a continuation of a block." "Return non-nil if current line is a continuation of a block."

View file

@ -1364,7 +1364,6 @@ delimiter."
"\\)\\>"))) "\\)\\>")))
(eq (ruby-deep-indent-paren-p t) 'space) (eq (ruby-deep-indent-paren-p t) 'space)
(not (bobp))) (not (bobp)))
(widen)
(goto-char (or begin parse-start)) (goto-char (or begin parse-start))
(skip-syntax-forward " ") (skip-syntax-forward " ")
(current-column)) (current-column))

View file

@ -341,9 +341,7 @@ This is used by `mhtml--pre-command'.")
((eq mhtml-tag-relative-indent 'ignore) ((eq mhtml-tag-relative-indent 'ignore)
(setq base-indent 0))) (setq base-indent 0)))
(narrow-to-region region-start (point-max)) (narrow-to-region region-start (point-max))
(let ((prog-indentation-context (list base-indent (let ((prog-indentation-context (list base-indent)))
(cons (point-min) nil)
nil)))
(mhtml--with-locals submode (mhtml--with-locals submode
;; indent-line-function was rebound by ;; indent-line-function was rebound by
;; mhtml--with-locals. ;; mhtml--with-locals.