Commit 5cc4f33b authored by Eli Zaretskii's avatar Eli Zaretskii

Document multi-mode indentation facilities

* doc/lispref/text.texi (Mode-Specific Indent): Document
'prog-indentation-context', 'prog-first-column', and 'prog-widen'.

* lisp/progmodes/prog-mode.el (prog-indentation-context)
(prog-widen): Doc fixes.
parent acae1834
......@@ -2362,6 +2362,84 @@ already indented, it calls @code{completion-at-point} to complete the
text at point (@pxref{Completion in Buffers}).
@end defopt
@cindex literate programming
@cindex multi-mode indentation
Some major modes need to support embedded regions of text whose
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
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.
@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:
@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
@end table
@end defvar
The following convenience functions should be used by major mode's
indentation engine in support of invocations as sub-modes of another
major mode.
@defun prog-first-column
Call this function instead of using a literal value (usually, zero) of
the column number for indenting top-level program constructs. The
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
......
......@@ -321,8 +321,17 @@ the ordering of object keys by default.
`json-pretty-print-buffer-ordered' pretty prints JSON objects with
object keys sorted alphabetically.
+++
** Prog mode has some support for multi-mode indentation.
See `prog-indentation-context' and `prog-widen'.
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
"Mode-Specific Indent" in the ELisp manual for more details.
** Prettify Symbols mode
......
......@@ -50,49 +50,51 @@
"Keymap used for programming modes.")
(defvar prog-indentation-context nil
"Non-nil while indenting embedded code chunks.
"When non-nil, provides context for indenting embedded code chunks.
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
main language to use the indentation engine of the sub mode for
lines in code chunks written in the sub language.
main language to use the indentation engine of the sub-mode for
lines in code chunks written in the sub-mode's language.
When a major mode of such a main language decides to delegate the
indentation of a line/region to the indentation engine of the sub
mode, it is supposed to bind this variable to non-nil around the call.
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 looks as follows
(FIRST-COLUMN (START . END) PREVIOUS-CHUNKS)
FIRST-COLUMN is the column the indentation engine of the sub mode
should usually choose for top-level language constructs inside
the code chunk (instead of 0).
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 to END is the region of the code chunk. See function
`prog-widen' for additional info.
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
the sub-mode with the virtual context of the code chunk. Valid
values are:
- A string containing code which the indentation engine can
- 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, it is valid and expected for the inner
mode to add text-properties to the string.
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
a corresponding function header.
to be indented like function bodies -- the string would contain
the corresponding function preamble.
- A function called with the start position of the current
chunk. It will return either the region of the previous chunk
as (PREV-START . PREV-END) or nil if there is no further
previous chunk.
- 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 code chunks of the
previous macro definitions for the same name.")
A typical use case are literate programming sources -- the
function would successively return the previous code chunks.")
(defun prog-indent-sexp (&optional defun)
"Indent the expression after point.
......@@ -113,8 +115,8 @@ instead."
(defun prog-widen ()
"Remove restrictions (narrowing) from current code chunk or buffer.
This function can be used instead of `widen' in any function used
by the indentation engine to make it respect the value
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
......@@ -122,8 +124,8 @@ This function (like `widen') is useful inside a
narrowing is in effect."
(let ((chunk (cadr prog-indentation-context)))
(if chunk
;; no widen necessary here, as narrow-to-region changes (not
;; just narrows) existing restrictions
;; 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))))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment