Sangrado masivo de Emacs para Python


132

Al trabajar con Python en Emacs si quiero agregar un try / except a un bloque de código, a menudo encuentro que tengo que sangrar todo el bloque, línea por línea. En Emacs, ¿cómo sangra todo el bloque a la vez?

No soy un usuario experimentado de Emacs, pero creo que es la mejor herramienta para trabajar a través de ssh. Estoy usando Emacs en la línea de comando (Ubuntu), no como una interfaz gráfica de usuario, si eso hace alguna diferencia.


55
C-c >por derecho. C-c <para izquierda
Thamme Gowda

Respuestas:


213

Si está programando Python usando Emacs, entonces probablemente debería estar usando el modo python. Con el modo python, después de marcar el bloque de código,

C-c >o C-c C-l desplaza la región 4 espacios a la derecha

C-c <o C-c C-r desplaza la región 4 espacios a la izquierda

Si necesita cambiar el código por dos niveles de sangría, o alguna cantidad arbitraria, puede anteponer el comando con un argumento:

C-u 8 C-c > desplaza la región 8 espacios a la derecha

C-u 8 C-c < desplaza la región 8 espacios a la izquierda

Otra alternativa es usar lo M-x indent-rigidlyque está obligado a C-x TAB:

C-u 8 C-x TAB desplaza la región 8 espacios a la derecha

C-u -8 C-x TAB desplaza la región 8 espacios a la izquierda

También son útiles los comandos de rectángulo que operan en rectángulos de texto en lugar de líneas de texto.

Por ejemplo, después de marcar una región rectangular,

C-x r o inserta espacio en blanco para llenar la región rectangular (efectivamente desplazando el código a la derecha)

C-x r k mata la región rectangular (efectivamente desplazando el código a la izquierda)

C-x r tsolicita una cadena para reemplazar el rectángulo con. Al ingresar C-u 8 <space>, se ingresarán 8 espacios.

PD. Con Ubuntu, para hacer que el modo python sea el modo predeterminado para todos los archivos .py, simplemente instale el python-modepaquete.


Gracias eso funciona perfectamente. con Emacs22, ¿no se habilita automáticamente el modo python con todos los archivos .py? De todos modos, el Cc> funciona bien.
Vernon

@Vernon: C-c >se define en python-mode.el, por lo que creo que debe haber instalado el python-modepaquete en algún lugar del camino. Me alegra que funcione para ti.
unutbu

1
Cc> funciona bien en Emacs 23.2 sin instalar el modo python, ya que funciona con el python.el proporcionado
codeasone

@landstatic: Gracias por la información. ¿Eso me hace pensar que quizás todos los comandos enumerados anteriormente funcionan igual para python-mode.el o python.el?
unutbu

2
@redobot: C-c C-ly C-c C-rdeben ser enlaces personalizados que haya configurado usted mismo. Si ejecuta emacs -q(para ejecutar emacs sin cargar un archivo init) verá que no hay enlace para C-c C-lo C-c C-ren modo Python.
unutbu

9

Además de indent-region, que está asignado C-M-\por defecto, los comandos de edición de rectángulo son muy útiles para Python. Marque una región como normal, luego:

  • C-x r t( string-rectangle): le solicitará los caracteres que desea insertar en cada línea; ideal para insertar un cierto número de espacios
  • C-x r k( kill-rectangle): elimina una región rectangular; ideal para eliminar sangría

También puede C-x r y( yank-rectangle), pero eso rara vez es útil.


4

indent-regionmapeado a C-M-\debería hacer el truco.


3
Este es un consejo terrible. La sangría de Python no se puede inferir (¡ya que es una sintaxis!), Por lo que ident-region es inútil.
Sam Clearman

1

He estado usando esta función para manejar mi sangría y sangría:

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

Y luego lo asigno a un atajo de teclado:

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

1

Soy un newb de Emacs, por lo que esta respuesta probablemente raya en inútil.

Ninguna de las respuestas mencionadas hasta ahora cubren la sangría de literales como dicto list. Por ejemplo, M-x indent-regiono M-x python-indent-shift-righty la compañía no van a ayudar si ha cortado y pegado el siguiente literal y necesita que se vuelva a sangrar con sensatez:

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

Parece que M-x indent-regiondebería hacer algo con sensatez python-mode, pero ese no es (todavía) el caso.

Para el caso específico donde sus literales están entre corchetes, usar TAB en las líneas en cuestión obtiene lo que desea (porque el espacio en blanco no juega un papel).

Así que lo que he estado haciendo en estos casos es la grabación rápidamente una macro de teclado al igual que <f3> C-n TAB <f4>como en F3, Ctrl-N (o flecha hacia abajo), TAB, F4, y luego usando F4 varias veces para aplicar la macro puede ahorrar un par de pulsaciones de teclas. O puedes hacerlo C-u 10 C-x epara aplicarlo 10 veces.

(Sé que no parece mucho, pero intente volver a sangrar 100 líneas de basura literal sin perder la flecha hacia abajo, y luego tener que subir 5 líneas y repetir cosas;)).


1

Yo uso el siguiente fragmento. En la pestaña cuando la selección está inactiva, sangra la línea actual (como lo hace normalmente); cuando la selección está inactiva, sangra toda la región a la derecha.

(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

Hacer sangría de forma interactiva.

  1. Seleccione la región a sangrar.
  2. Cx TAB.
  3. Use las flechas ( <-y ->) para sangrar interactivamente.
  4. Presione Esctres veces cuando haya terminado con la sangría requerida.

Copiado de mi publicación en: sangrar varias líneas en Emacs


-2

Hago algo como esto 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
Dado que el espacio en blanco es parte de la sintaxis en Python, indent-region en todo el archivo es una mala idea.
Daniel Stutzbach
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.