Emacs: добавить do / while & if / else как исключения для электрического режима c (}) - PullRequest
0 голосов
/ 24 мая 2010

Если для c-auto-newline задано значение, отличное от nil, оно переопределяет текущую строку и вставляет возврат каретки, а затем выравнивает новую строку.Тем не мение.Я использую стиль отступа 1TBS (с 4 пробелами), что означает, что операторы / else делаются так:

if (n == 1) {
    exit(EXIT_SUCCESS);
} else {
    perror("n");
}

Кроме того, я пишу циклы записи do / while так:

do {
    printf("%d\n", n++);
} while (n < 64);

Таким образом, хотя я хочу, чтобы новая строка автоматически вставлялась после каждой открывающей скобки и точки с запятой, я не хочу, чтобы новые строки автоматически вставлялись после завершения оператора if или do с закрывающей скобкой.

Как я могу заставить GNU Emacs (23.2.1, * nix; или последнюю версию CVS) выборочно вставлять подобные строки?Вдоль тех же строк можно ли в Emacs вставить открывающую скобку, символ новой строки и закрывающую скобку на другой символ новой строки, поместив курсор в середину двух скобок после закрывающих скобок после оператора if, объявления функции и т. П.

1 Ответ

2 голосов
/ 24 мая 2010

На этой странице руководства по работе с cc-режимом описывается, как сделать отступы в режиме cc-режима и формат авто-новой строки в цикле do-while.

Вам нужно будет отрегулировать это для обработки случая if / else.

Что касается последнего - я не мог понять, как сделать это разумно с помощью cc-mode, поэтому я написал новую функцию для этого.

(defun csharp-insert-open-brace ()
  "Intelligently insert a pair of curly braces. This fn is most
often bound to the open-curly brace, with

    (local-set-key (kbd \"{\") 'csharp-insert-open-brace)

The default binding for an open curly brace in cc-modes is often
`c-electric-brace' or `skeleton-pair-insert-maybe'.  The former
can be configured to insert newlines around braces in various
syntactic positions.  The latter inserts a pair of braces and
then does not insert a newline, and does not indent.

This fn provides another option, with some additional
intelligence for csharp-mode.  When you type an open curly, the
appropriate pair of braces appears, with spacing and indent set
in a context-sensitive manner.

Within a string literal, you just get a pair of braces, and point
is set between them. Following an equals sign, you get a pair of
braces, with a semincolon appended. Otherwise, you
get the open brace on a new line, with the closing brace on the
line following, and point on the line between.

There may be another way to get this to happen appropriately just
within emacs, but I could not figure out how to do it.  So I
wrote this alternative.

"
  (interactive)
  (let
      (tpoint
       (in-string (string= (csharp-in-literal) "string"))
       (preceding3
        (save-excursion
          (and
           (skip-chars-backward " \t")
           (> (- (point) 2) (point-min))
           (buffer-substring-no-properties (point) (- (point) 3)))))
       (one-word-back
        (save-excursion
          (backward-word 2)
          (thing-at-point 'word))))

    (cond

     ;; Case 1: inside a string literal?
     ;; --------------------------------------------
     ;; If so, then just insert a pair of braces and put the point
     ;; between them.  The most common case is a format string for
     ;; String.Format() or Console.WriteLine().
     (in-string
      (self-insert-command 1)
      (insert "}")
      (backward-char))

     ;; Case 2: the open brace starts an array initializer.
     ;; --------------------------------------------
     ;; When the last non-space was an equals sign or square brackets,
     ;; then it's an initializer.
     ((save-excursion
        (and (c-safe (backward-sexp) t)
             (looking-at "\\(\\w+\\b *=\\|[[]]+\\)")))
      (self-insert-command 1)
      (insert "  };")
      (backward-char 3))

     ;; Case 3: the open brace starts an instance initializer
     ;; --------------------------------------------
     ;; If one-word-back was "new", then it's an object initializer.
     ((string= one-word-back "new")
      (save-excursion
        (message "object initializer")
        (setq tpoint (point)) ;; prepare to indent-region later
        (newline)
        (self-insert-command 1)
        (newline-and-indent)
        (newline)
        (insert "};")
        (c-indent-region tpoint (point))
        (previous-line)
        (indent-according-to-mode)
        (end-of-line)
        (setq tpoint (point)))
      (goto-char tpoint))

     ;; Case 4: a lambda initialier.
     ;; --------------------------------------------
     ;; If the open curly follows =>, then it's a lambda initializer.
     ((string= (substring preceding3 -2) "=>")
      (message "lambda init")
      (self-insert-command 1)
      (insert "  }")
      (backward-char 2))

     ;; else, it's a new scope. (if, while, class, etc)
     (t
      (save-excursion
        (message "new scope")
        (set-mark (point)) ;; prepare to indent-region later
        ;; check if the prior sexp is on the same line
        (if (save-excursion
              (let ((curline (line-number-at-pos))
                    (aftline (progn
                               (if (c-safe (backward-sexp) t)
                                   (line-number-at-pos)
                                 -1))))
                (= curline aftline)))
            (newline-and-indent))
        (self-insert-command 1)
        (c-indent-line-or-region)
        (end-of-line)
        (newline)
        (insert "}")
        ;;(c-indent-command) ;; not sure of the difference here
        (c-indent-line-or-region)
        (previous-line)
        (end-of-line)
        (newline-and-indent)
        ;; point ends up on an empty line, within the braces, properly indented
        (setq tpoint (point)))

      (goto-char tpoint)))))

Вы должны заменить csharp-in-literal выше на c-in-literal, чтобы использовать его в любом режиме cc. Если вы сделали это, вам также нужно изменить некоторые случаи в этом fn. Вы хотели бы изменить инициализатор массива и инициализатор объекта, так как я думаю, что они являются новыми для c #.

...