Indentation en bloc Emacs pour Python

132

Travailler avec Python dans Emacs si je veux ajouter un try / except à un bloc de code, je trouve souvent que je dois indenter tout le bloc, ligne par ligne. Dans Emacs, comment indenter le bloc entier à la fois.

Je ne suis pas un utilisateur expérimenté d'Emacs, mais je trouve juste que c'est le meilleur outil pour travailler avec ssh. J'utilise Emacs en ligne de commande (Ubuntu), pas en tant qu'interface graphique, si cela fait une différence.

Vernon
la source
5
C-c >pour le droit. C-c <à gauche
Thamme Gowda

Réponses:

213

Si vous programmez Python avec Emacs, vous devriez probablement utiliser le mode python. Avec le mode python, après avoir marqué le bloc de code,

C-c >ou C-c C-l décale la région de 4 espaces vers la droite

C-c <ou C-c C-r décale la région de 4 espaces vers la gauche

Si vous avez besoin de décaler le code de deux niveaux d'indention, ou d'un montant arbitraire, vous pouvez préfixer la commande avec un argument:

C-u 8 C-c > décale la région de 8 espaces vers la droite

C-u 8 C-c < décale la région de 8 espaces vers la gauche

Une autre alternative est d'utiliser M-x indent-rigidlyce qui est lié à C-x TAB:

C-u 8 C-x TAB décale la région de 8 espaces vers la droite

C-u -8 C-x TAB décale la région de 8 espaces vers la gauche

Les commandes de rectangle qui fonctionnent sur des rectangles de texte au lieu de lignes de texte sont également utiles .

Par exemple, après avoir marqué une région rectangulaire,

C-x r o insère un espace vide pour remplir la zone rectangulaire (en déplaçant effectivement le code vers la droite)

C-x r k tue la région rectangulaire (déplaçant effectivement le code vers la gauche)

C-x r tdemande une chaîne pour remplacer le rectangle par. La saisie C-u 8 <space>entrera alors 8 espaces.

PS. Avec Ubuntu, pour faire du mode python le mode par défaut pour tous les fichiers .py, installez simplement le python-modepackage.

unutbu
la source
Merci qui fonctionne parfaitement. avec Emacs22, le mode python n'est-il pas automatiquement activé avec tous les fichiers .py? Quoi qu'il en soit, le Cc> fonctionne très bien.
Vernon
@Vernon: C-c >est défini dans python-mode.el, donc je pense que vous devez avoir installé le python-modepaquet quelque part en cours de route. Heureux que cela fonctionne pour vous.
unutbu
1
Cc> fonctionne très bien dans Emacs 23.2 sans installer le mode python car il fonctionne avec le python.el fourni
codeasone
@landstatic: Merci pour l'information. Cela me fait penser que toutes les commandes énumérées ci-dessus fonctionnent peut-être de la même manière pour python-mode.el ou python.el?
unutbu le
2
@redobot: C-c C-let C-c C-rdoivent être des liaisons personnalisées que vous avez configurées vous-même. Si vous exécutez emacs -q(pour exécuter emacs sans charger de fichier d'initialisation), vous verrez qu'il n'y a pas de liaison pour C-c C-lou C-c C-ren mode Python.
unutbu
9

En plus de indent-region, qui est mappé C-M-\par défaut, les commandes d'édition de rectangle sont très utiles pour Python. Marquez une région comme normale, puis:

  • C-x r t( string-rectangle): vous demandera les caractères que vous souhaitez insérer dans chaque ligne; idéal pour insérer un certain nombre d'espaces
  • C-x r k( kill-rectangle): supprime une région rectangle; idéal pour supprimer l'indentation

Vous pouvez également C-x r y( yank-rectangle), mais ce n'est que rarement utile.

Daniel Stutzbach
la source
4

indent-regionmappé à C-M-\devrait faire l'affaire.

Łukasz
la source
3
C'est un conseil terrible. L'indentation Python ne peut pas être déduite (car c'est de la syntaxe!) Donc ident-region est inutile.
Sam Clearman
1

J'ai utilisé cette fonction pour gérer mon indentation et ma désindentation:

(defun unindent-dwim (&optional count-arg)
  "Keeps relative spacing in the region.  Unindents to the next multiple of the current tab-width"
  (interactive)
  (let ((deactivate-mark nil)
        (beg (or (and mark-active (region-beginning)) (line-beginning-position)))
        (end (or (and mark-active (region-end)) (line-end-position)))
        (min-indentation)
        (count (or count-arg 1)))
    (save-excursion
      (goto-char beg)
      (while (< (point) end)
        (add-to-list 'min-indentation (current-indentation))
        (forward-line)))
    (if (< 0 count)
        (if (not (< 0 (apply 'min min-indentation)))
            (error "Can't indent any more.  Try `indent-rigidly` with a negative arg.")))
    (if (> 0 count)
        (indent-rigidly beg end (* (- 0 tab-width) count))
      (let (
            (indent-amount
             (apply 'min (mapcar (lambda (x) (- 0 (mod x tab-width))) min-indentation))))
        (indent-rigidly beg end (or
                                 (and (< indent-amount 0) indent-amount)
                                 (* (or count 1) (- 0 tab-width))))))))

Et puis je l'assigne à un raccourci clavier:

(global-set-key (kbd "s-[") 'unindent-dwim)
(global-set-key (kbd "s-]") (lambda () (interactive) (unindent-dwim -1)))
Singleton
la source
1

Je suis un newb d'Emacs, donc cette réponse est probablement presque inutile.

Aucune des réponses mentionnées jusqu'à présent ne couvre la ré-indentation de littéraux comme dictou list. Par exemple, M-x indent-regionou M-x python-indent-shift-rightet compagnie ne vous aideront pas si vous avez copié-collé le littéral suivant et que vous avez besoin qu'il soit ré-indenté judicieusement:

    foo = {
  'bar' : [
     1,
    2,
        3 ],
      'baz' : {
     'asdf' : {
        'banana' : 1,
        'apple' : 2 } } }

On a l'impression de M-x indent-regiondevoir faire quelque chose de sensé python-mode, mais ce n'est pas (encore) le cas.

Pour le cas spécifique où vos littéraux sont entre crochets, l'utilisation de TAB sur les lignes en question obtient ce que vous voulez (car les espaces ne jouent pas de rôle).

Donc, ce que j'ai fait dans de tels cas, c'est enregistrer rapidement une macro de clavier comme <f3> C-n TAB <f4>en F3, Ctrl-n (ou flèche vers le bas), TAB, F4, puis utiliser F4 à plusieurs reprises pour appliquer la macro peut enregistrer quelques frappes. Ou vous pouvez l' C-u 10 C-x eappliquer 10 fois.

(Je sais que cela ne sonne pas beaucoup, mais essayez de ré-indenter 100 lignes de déchets littéraux sans manquer la flèche vers le bas, puis de devoir remonter de 5 lignes et de répéter les choses;)).

Rob
la source
1

J'utilise l'extrait suivant. Sur tabulation lorsque la sélection est inactive, il met en retrait la ligne courante (comme il le fait normalement); lorsque la sélection est inactive, elle indente toute la région vers la droite.

(defun my-python-tab-command (&optional _)
  "If the region is active, shift to the right; otherwise, indent current line."
  (interactive)
  (if (not (region-active-p))
      (indent-for-tab-command)
    (let ((lo (min (region-beginning) (region-end)))
          (hi (max (region-beginning) (region-end))))
      (goto-char lo)
      (beginning-of-line)
      (set-mark (point))
      (goto-char hi)
      (end-of-line)
      (python-indent-shift-right (mark) (point)))))
(define-key python-mode-map [remap indent-for-tab-command] 'my-python-tab-command)
mookid
la source
1

Faites l'indentation de manière interactive.

  1. Sélectionnez la région à mettre en retrait.
  2. Cx TAB.
  3. Utilisez les flèches ( <-et ->) pour indenter de manière interactive.
  4. Appuyez Esctrois fois lorsque vous avez terminé avec l'indentation requise.

Copié de mon message dans: Retrait de plusieurs lignes dans Emacs

vignes
la source
-2

Je fais quelque chose comme ça universellement

;; intent whole buffer 
(defun iwb ()
  "indent whole buffer"
  (interactive)
  ;;(delete-trailing-whitespace)
  (indent-region (point-min) (point-max) nil)
  (untabify (point-min) (point-max)))
hpavc
la source
2
Comme les espaces font partie de la syntaxe en Python, indent-region sur l'ensemble du fichier est une mauvaise idée.
Daniel Stutzbach