Emacs indent bulk per Python


132

Lavorando con Python in Emacs se voglio aggiungere un tentativo / tranne a un blocco di codice, trovo spesso che devo indentare l'intero blocco, riga per riga. In Emacs, come indentare l'intero blocco in una volta.

Non sono un utente esperto di Emacs, ma trovo che sia lo strumento migliore per lavorare con ssh. Sto usando Emacs sulla riga di comando (Ubuntu), non come interfaccia grafica, se questo fa la differenza.


5
C-c >per giusto. C-c <per sinistra
Thamme Gowda,

Risposte:


213

Se stai programmando Python usando Emacs, probabilmente dovresti usare la modalità Python. Con la modalità Python, dopo aver contrassegnato il blocco di codice,

C-c >o C-c C-l sposta la regione di 4 spazi a destra

C-c <o C-c C-r sposta la regione di 4 spazi a sinistra

Se è necessario spostare il codice di due livelli di rientro o un importo arbitrario, è possibile aggiungere il prefisso al comando con un argomento:

C-u 8 C-c > sposta la regione di 8 spazi a destra

C-u 8 C-c < sposta la regione di 8 spazi a sinistra

Un'altra alternativa è l'uso M-x indent-rigidlyche è legato a C-x TAB:

C-u 8 C-x TAB sposta la regione di 8 spazi a destra

C-u -8 C-x TAB sposta la regione di 8 spazi a sinistra

Utili anche i comandi di rettangolo che operano su rettangoli di testo anziché su righe di testo.

Ad esempio, dopo aver contrassegnato una regione rettangolare,

C-x r o inserisce uno spazio vuoto per riempire la regione rettangolare (spostando efficacemente il codice a destra)

C-x r k uccide la regione rettangolare (spostando effettivamente il codice a sinistra)

C-x r trichiede una stringa con cui sostituire il rettangolo. Entrando C-u 8 <space>entrerai quindi in 8 spazi.

PS. Con Ubuntu, per rendere la modalità Python la modalità predefinita per tutti i file .py, è sufficiente installare il python-modepacchetto.


Grazie che funziona perfettamente. con Emacs22 la modalità Python non è abilitata automaticamente con tutti i file .py? Comunque, il Cc> funziona bene.
Vernon,

@Vernon: C-c >è definito in python-mode.el, quindi penso che tu abbia installato il python-modepacchetto da qualche parte lungo la strada. Sono contento che funzioni per te.
unutbu,

1
Cc> funziona bene in Emacs 23.2 senza installare la modalità Python in quanto funziona con il python.el fornito
codeasone

@landstatic: grazie per l'informazione. Questo mi fa pensare che forse tutti i comandi sopra elencati funzionano allo stesso modo per python-mode.el o python.el?
unutbu,

2
@redobot: C-c C-le C-c C-rdevono essere attacchi personalizzati che hai impostato tu stesso. Se esegui emacs -q(per eseguire emacs senza caricare un file init) noterai che non esiste alcun legame per C-c C-lo C-c C-rin modalità Python.
unutbu, del

9

Inoltre indent-region, per C-M-\impostazione predefinita, i comandi di modifica del rettangolo sono molto utili per Python. Contrassegna una regione come normale, quindi:

  • C-x r t( string-rectangle): ti chiederà i caratteri che desideri inserire in ogni riga; ottimo per inserire un certo numero di spazi
  • C-x r k( kill-rectangle): rimuove una regione rettangolare; ottimo per rimuovere il rientro

Puoi anche C-x r y( yank-rectangle), ma solo raramente è utile.


4

indent-regionmappato su C-M-\dovrebbe fare il trucco.


3
Questo è un consiglio terribile. Il rientro di Python non può essere dedotto (poiché è sintassi!), Quindi ident-region è inutile.
Sam Clearman,

1

Sto usando questa funzione per gestire il rientro e il rientro:

(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))))))))

E poi lo assegno a una scorciatoia da tastiera:

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

1

Sono un novellino di Emacs, quindi questa risposta probabilmente confina con inutile.

Nessuna delle risposte menzionate finora copre il rientro di letterali come dicto list. Ad esempio, M-x indent-regiono M-x python-indent-shift-righte compagnia non stanno andando aiuto se hai tagliato e incollato il seguente letterale e bisogno di essere ri-rientrato sensibilmente:

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

Sembra che M-x indent-regiondovrebbe fare qualcosa di sensato python-mode, ma non è (ancora) il caso.

Per il caso specifico in cui i tuoi letterali sono tra parentesi, l'uso di TAB sulle righe in questione ottiene ciò che desideri (perché gli spazi bianchi non hanno un ruolo).

Quindi quello che ho fatto in questi casi sta rapidamente la registrazione di una macro di tastiera come <f3> C-n TAB <f4>come in F3, Ctrl-n (o freccia giù), TAB, F4, F4 e quindi utilizzando più volte per applicare la macro può risparmiare un paio di tasti. Oppure puoi fare C-u 10 C-x eper applicarlo 10 volte.

(So ​​che non suona molto, ma prova a rientrare di nuovo 100 righe di immondizia letterale senza perdere la freccia verso il basso, quindi devi salire di 5 righe e ripetere le cose;)).


1

Uso il seguente frammento. Nella scheda quando la selezione è inattiva, rientra la riga corrente (come fa normalmente); quando la selezione è inattiva, rientra a destra l'intera regione.

(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)

1

Effettua il rientro in modo interattivo.

  1. Seleziona la regione da rientrare.
  2. Cx TAB.
  3. Utilizzare le frecce ( <-e ->) per rientrare in modo interattivo.
  4. Premi Esctre volte quando hai finito con il rientro richiesto.

Copiato dal mio post in: Indentare diverse righe in Emacs


-2

Faccio qualcosa del genere universalmente

;; intent whole buffer 
(defun iwb ()
  "indent whole buffer"
  (interactive)
  ;;(delete-trailing-whitespace)
  (indent-region (point-min) (point-max) nil)
  (untabify (point-min) (point-max)))

2
Poiché lo spazio bianco fa parte della sintassi in Python, indent-region sull'intero file è una cattiva idea.
Daniel Stutzbach,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.