44 votes

Modèles C ++ et Emacs: Personnalisation de l'indentation

Autant que je sache, dans emacs, il n'existe aucun moyen de personnaliser le niveau de retrait de la clôture caractère '>' d'un modèle de liste en C++. Actuellement, mon emacs indentation régime fait ceci:

template <
    typename T1,
    typename T2,
    typename T3
    >
class X;

Ce que je veux, c'est quelque chose comme ceci:

template <
    typename T1,
    typename T2,
    typename T3
>
class X;

Réglage de l'alinéa de la variable de template-args-suite à zéro tiret le caractère '>' correctement, mais au prix de unindenting le corps même du modèle de la liste d'arguments.

Toutes les suggestions de la emacs gourous là-bas?

EDIT:

Je l'ai eu un peu de travail avec la suite de hack:

(defun indent-templates (elem)
  (c-langelem-col elem t)
  (let ((current-line
         (buffer-substring-no-properties
          (point-at-bol) (point-at-eol))))
    (if (string-match-p "^\\s-*>" current-line)
        0
        '+)))

Et puis, la définition du modèle-args-suite à tiret-modèles dans mon thème personnalisé, ala:

(c-add-style "my-style"
             '("stroustrup"
                ;; ... Other stuff ...
                (template-args-cont . indent-templates))))

Mais c'est encore assez buggé. Il fonctionne la plupart du temps, mais parfois emacs se confond pense à un modèle de liste de est une arglist, puis de l'hilarité qui s'ensuit.

2voto

mrenaud Points 491

La meilleure solution que j'ai trouvé l'écriture est une coutume (et relativement simple) logement de fonction.

Le Code

(defun c++-template-args-cont (langelem)
"Control indentation of template parameters handling the special case of '>'.
Possible Values:
0   : The first non-ws character is '>'. Line it up under 'template'.
nil : Otherwise, return nil and run next lineup function."
  (save-excursion
    (beginning-of-line)
    (if (re-search-forward "^[\t ]*>" (line-end-position) t)
        0)))

(add-hook 'c++-mode-hook
          (lambda ()
            (c-set-offset 'template-args-cont
                          '(c++-template-args-cont c-lineup-template-args +))))

Cela gère tous les cas que j'ai rencontré, même avec des modèles imbriqués plusieurs niveaux de profondeur.

Comment Ça Marche

Pour l'indentation du code, si une liste d'indentation fonctions est fourni, alors Emacs vais essayer dans l'ordre, et si celui actuellement en cours d'exécution renvoie nil, il appellera à la prochaine. Ce que j'ai fait est ajouté une nouvelle fonction de l'indentation pour le début de la liste qui détecte si le premier caractère non-blanc sur la ligne">", et si elle l'est, définissez le retrait à la position 0 (qui sera en ligne avec l'ouverture d'un modèle). Cela couvre également le cas où vous avez un modèle paramètres du modèle comme suit:

template <
  template <
    typename T,
    typename U,
    typename... Args
  > class... CS
>

parce qu'il ne se soucie pas de ce qui est après le '>'. Donc, comme un résultat de la façon dont la liste d'indentation fonctions œuvres, si '>' n'est pas le premier caractère, la fonction retourne l' nil et l'habitude de l'indentation de la fonction appelée.

1voto

assem Points 1038

Commentaires

Je pense en partie le problème que vous avez de l'expérience, c'est que lorsque vous instanciez modèles, emacs CC mode de vues avec le même template-args-cont de la structure. Donc, en prenant cela en compte, j'ai élargi sur votre idée de départ et essayé de faire en fonction de mon goût; j'ai fait le code détaillé, dans l'espoir que tout le monde peut comprendre mon intention. :) Cela ne devrait pas causer des problèmes lorsque vous instanciez, et il apparaît également à travailler pour modèle les paramètres de modèle! Essayez ceci jusqu'à ce que quelqu'un avec plus d'Elisp compétences peuvent fournir une meilleure solution!

Si vous rencontrez un 'combat' (c'est à dire en alternance ou cassé indentation), essayez de recharger le fichier cpp , C-xC-v à l'Entrée et à la mise en retrait de nouveau. Parfois avec modèle de paramètres de modèle emacs montre l'intérieur des arguments arglist-cont-nonempty , et même de suppléants en arrière avec template-args-const, mais le reload toujours l'état restauré.

L'utilisation de la

Pour faire ce que vous voulez faire un essai en utilisant le code ci-dessous et de les ajouter à votre c-offsets-alist une entrée:

(template-args-cont . brian-c-lineup-template-args)

et définissez la variable

(setq brian-c-lineup-template-closebracket t)

Je préfère un alignement légèrement différent:

(setq brian-c-lineup-template-closebracket 'under)

Code

(defvar brian-c-lineup-template-closebracket 'under 
  "Control the indentation of the closing template bracket, >.
Possible values and consequences:
'under : Align directly under (same column) the opening bracket.
t      : Align at the beginning of the line (or current indentation level.
nil    : Align at the same column of previous types (e.g. col of class T).")

(defun brian-c-lineup-template--closebracket-p ()
  "Return t if the line contains only a template close bracket, >."
  (save-excursion 
    (beginning-of-line)
    ;; Check if this line is empty except for the trailing bracket, >
    (looking-at (rx (zero-or-more blank)
            ">"
            (zero-or-more blank)))))

(defun brian-c-lineup-template--pos-to-col (pos)
  (save-excursion
    (goto-char pos)
    (current-column)))

(defun brian-c-lineup-template--calc-open-bracket-pos (langelem)
  "Calculate the position of a template declaration opening bracket via LANGELEM."
  (save-excursion 
    (c-with-syntax-table c++-template-syntax-table
      (goto-char (c-langelem-pos langelem))
      (1- (re-search-forward "<" (point-max) 'move)))))

(defun brian-c-lineup-template--calc-indent-offset (ob-pos)
  "Calculate the indentation offset for lining up types given the opening 
bracket position, OB-POS."
  (save-excursion
    (c-with-syntax-table c++-template-syntax-table
      ;; Move past the opening bracket, and check for types (basically not space)
      ;; if types are on the same line, use their starting column for indentation.
      (goto-char (1+ ob-pos))
      (cond ((re-search-forward (rx 
                 (or "class"
                     "typename"
                     (one-or-more (not blank))))
                (c-point 'eol)
                'move)
         (goto-char (match-beginning 0))
         (current-column))
        (t
         (back-to-indentation)
         (+ c-basic-offset (current-column)))))))

(defun brian-c-lineup-template-args (langelem)
  "Align template arguments and the closing bracket in a semi-custom manner."
  (let* ((ob-pos (brian-c-lineup-template--calc-open-bracket-pos langelem))
     (ob-col (brian-c-lineup-template--pos-to-col ob-pos))
     (offset (brian-c-lineup-template--calc-indent-offset ob-pos)))

    ;; Optional check for a line consisting of only a closebracket and
    ;; line it up either at the start of indentation, or underneath the
    ;; column of the opening bracket
    (cond ((and brian-c-lineup-template-closebracket
          (brian-c-lineup-template--closebracket-p))
         (cond ((eq brian-c-lineup-template-closebracket 'under)
            (vector ob-col))
           (t
            0)))
        (t
         (vector offset)))))

0voto

Tim Hoolihan Points 6982

C'est une approche différente que de changer les onglets, mais qu'en est-il de l'utilisation d'un système d' extraits de code comme Yasnippet (voir des exemples ici ).

Le seul problème est que si vous reformatez la documentation "Mx index-region" (ou cette section), elle retournera probablement aux autres règles de tabulation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X