[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Indenting the code written in square brackets as optional parameters

From: Arash Esbati
Subject: Re: Indenting the code written in square brackets as optional parameters
Date: Wed, 09 Mar 2022 17:54:31 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50

Sašo Živanović <> writes:

> However, as a long-time user of the []-based indentation, I can
> confidently say that counting *brackets []* (not braces {}) in
> comments is quite crucial for user's happiness. And not only in math
> mode, as noted by others in this thread, also in text (well,
> programming) mode, as in:
> \def\memoize{%
>   \@ifnextchar[\memoize@opt\memoize@noopt%]
> }

That's a good example, I haven't that in my mind.

> There might even be another usage case for taking commented delimites
> into account, indenting \ifs:
> \ifx ... %[
>   ...
> \fi %]
> (I'm totally alergic to non-indented \ifs, and have even tried to hack
> into that, but due to the coexistence of TeX- and LaTeX-style \ifs,
> this seems impossible to implement in general.)

Fixing this was on my list for a long time.  I think it should be doable
by patching the functions `LaTeX-indent-calculate',
`LaTeX-indent-level-count' and `LaTeX-indent-calculate-last'.  These are
my additions/changes which give the following results:


As you can see the \fi part is still broken.  Do you want to a look at
it?  I currently don't have the time to dive into it (search for ADDED):

--8<---------------cut here---------------start------------->8---
(defun LaTeX-indent-calculate (&optional force-type)
  "Return the indentation of a line of LaTeX source.
FORCE-TYPE can be used to force the calculation of an inner or
outer indentation in case of a commented line.  The symbols
'inner and 'outer are recognized."
    (LaTeX-back-to-indentation force-type)
    (let ((i 0)
          (list-length (safe-length docTeX-indent-inner-fixed))
          (case-fold-search nil)
      (cond ((save-excursion (beginning-of-line) (bobp)) 0)
            ((and (eq major-mode 'doctex-mode)
                    (while (and (< i list-length)
                                (not found))
                      (setq entry (nth i docTeX-indent-inner-fixed))
                      (when (looking-at (nth 0 entry))
                        (setq found t))
                      (setq i (1+ i)))
             (if (nth 2 entry)
                 (- (nth 1 entry) (if (integerp comment-padding)
                                    (length comment-padding)))
               (nth 1 entry)))
            ((looking-at (concat (regexp-quote TeX-esc)
                                 (LaTeX-verbatim-regexp t)
             ;; \end{verbatim} must be flush left, otherwise an unwanted
             ;; empty line appears in LaTeX's output.
            ((and LaTeX-indent-environment-check
                  ;; Special environments.
                  (let ((entry (assoc (or LaTeX-current-environment
                    (and entry
                         (nth 1 entry)
                         (funcall (nth 1 entry))))))
            ((looking-at (concat (regexp-quote TeX-esc)
             ;; Backindent at \end.
             (- (LaTeX-indent-calculate-last force-type) LaTeX-indent-level))
            ((looking-at (concat (regexp-quote TeX-esc) "right\\b"))
             ;; Backindent at \right.
             (- (LaTeX-indent-calculate-last force-type)
            ((looking-at (concat (regexp-quote TeX-esc)
                                 ;; ADDED: was only
                                 ;; LaTeX-item-regexp
                                 (concat LaTeX-item-regexp "\\|else\\b")
             ;; Items.
             (+ (LaTeX-indent-calculate-last force-type) LaTeX-item-indent))
            ((looking-at "}")
             ;; End brace in the start of the line.
             (- (LaTeX-indent-calculate-last force-type)
            (t (LaTeX-indent-calculate-last force-type))))))

(defun LaTeX-indent-level-count ()
  "Count indentation change caused by all \\left, \\right, \\begin, and
\\end commands in the current line."
      (let ((count 0))
        (narrow-to-region (point)
                             (concat "[^" TeX-esc "]"
                                     "\\(" LaTeX-indent-comment-start-regexp
        (while (search-forward TeX-esc nil t)
           ((looking-at "left\\b")
            (setq count (+ count LaTeX-left-right-indent-level)))
           ((looking-at "right\\b")
            (setq count (- count LaTeX-left-right-indent-level)))
           ((looking-at LaTeX-begin-regexp)
            (setq count (+ count LaTeX-indent-level)))
           ((looking-at LaTeX-end-regexp)
            (setq count (- count LaTeX-indent-level)))
           ;; ADDED: The next 4 lines
           ((looking-at "if[a-zA-Z@]*\\b")
            (setq count (+ count LaTeX-indent-level)))
           ((looking-at "fi\\b")
            (setq count (- count LaTeX-indent-level)))
           ((looking-at (regexp-quote TeX-esc))
            (forward-char 1))))

(defun LaTeX-indent-calculate-last (&optional force-type)
  "Return the correct indentation of a normal line of text.
The point is supposed to be at the beginning of the current line.
FORCE-TYPE can be used to force the calculation of an inner or
outer indentation in case of a commented line.  The symbols
'inner and 'outer are recognized."
  (let (line-comment-current-flag
    (setq line-comment-current-flag (TeX-in-line-comment)
          comment-current-flag (TeX-in-commented-line))
    (if comment-current-flag
        (skip-chars-backward "%\n\t ")
      (skip-chars-backward "\n\t "))
    ;; If we are called in a non-comment line, skip over comment
    ;; lines.  The computation of indentation should in this case
    ;; rather take the last non-comment line into account.
    ;; Otherwise there might arise problems with e.g. multi-line
    ;; code comments.  This behavior is not enabled in docTeX mode
    ;; where large amounts of line comments may have to be skipped
    ;; and indentation should not be influenced by unrelated code in
    ;; other macrocode environments.
    (while (and (not (eq major-mode 'doctex-mode))
                (not comment-current-flag)
                (not (bobp)))
      (skip-chars-backward "\n\t ")
    (setq line-comment-last-flag (TeX-in-line-comment)
          comment-last-flag (TeX-in-commented-line))
    (LaTeX-back-to-indentation force-type)
    ;; Separate line comments and other stuff (normal text/code and
    ;; code comments).  Additionally we don't want to compute inner
    ;; indentation when a commented and a non-commented line are
    ;; compared.
    (cond ((or (and (eq major-mode 'doctex-mode)
                    (or (and line-comment-current-flag
                             (not line-comment-last-flag))
                        (and (not line-comment-current-flag)
               (and force-type
                    (eq force-type 'inner)
                    (or (and comment-current-flag
                             (not comment-last-flag))
                        (and (not comment-current-flag)
          ((looking-at (concat (regexp-quote TeX-esc)
                               "begin *{\\("
           ;; I dislike having all of the document indented...
           (+ (LaTeX-current-indentation force-type)
              ;; Some people have opening braces at the end of the
              ;; line, e.g. in case of `\begin{letter}{%'.
          ((and (eq major-mode 'doctex-mode)
                (looking-at (concat (regexp-quote TeX-esc)
                                    "end[ \t]*{macrocode\\*?}"))
           ;; Reset indentation to zero after a macrocode
           ;; environment.
          ((looking-at (concat (regexp-quote TeX-esc)
                               "begin *{"
                               ;; Don't give optional argument here
                               ;; because indent would be disabled
                               ;; inside comment env otherwise.
          ((looking-at (concat (regexp-quote TeX-esc)
                               "end *{"
                               (LaTeX-verbatim-regexp t)
           ;; If I see an \end{verbatim} in the previous line I skip
           ;; back to the preceding \begin{verbatim}.
             (if (re-search-backward (concat (regexp-quote TeX-esc)
                                             "begin *{"
                                             (LaTeX-verbatim-regexp t)
                                             "}") 0 t)
                 (LaTeX-indent-calculate-last force-type)
          (t (+ (LaTeX-current-indentation force-type)
                (if (not (and force-type
                              (eq force-type 'outer)
                    (+ (LaTeX-indent-level-count)
                (cond ((looking-at (concat (regexp-quote TeX-esc)
                        (concat (regexp-quote TeX-esc) "right\\b"))
                      ((looking-at (concat (regexp-quote TeX-esc)
                                           ;; ADDED: was only LaTeX-item-regexp
                                           (concat LaTeX-item-regexp 
                       (- LaTeX-item-indent))
                      ((looking-at "}")
                      (t 0)))))))
--8<---------------cut here---------------end--------------->8---

> Finally, I believe that if we're about to extend the indenting
> mechanism, it makes sense to implement in generally enough to allow
> for arbitrary, and configurable, delimiters. For one, we can then set
> the default to {} to guarantee unchanged default behaviour. Secondly,
> I got quite attached to seeing stuff like this:
> ------
> develop a syntactic counterpart to conservativity (recall the
>   discussion of generalized quantifiers in
>   section~\ref{cha:generalized-quantifier-theory}), and ultimately our
> understanding of determiners and the nature of quantification in natural
> language itself.
> ------
> And perhaps someone will develop a package using <> as delimiters for
> whatever, etc.

I'm not sure, isn't this sort of overkill?

Best, Arash

reply via email to

[Prev in Thread] Current Thread [Next in Thread]