Wcięcie zbiorcze Emacsa dla Pythona

133

Pracując z Pythonem w Emacsie, jeśli chcę dodać try / z wyjątkiem do bloku kodu, często stwierdzam, że muszę wciąć cały blok, wiersz po wierszu. W Emacs, jak wciąć cały blok na raz.

Nie jestem doświadczonym użytkownikiem Emacsa, ale po prostu uważam, że jest to najlepsze narzędzie do pracy z ssh. Używam Emacsa w wierszu poleceń (Ubuntu), a nie jako GUI, jeśli to robi jakąkolwiek różnicę.

Vernon
źródło
5
C-c >za słuszne. C-c <po lewej
Thamme Gowda

Odpowiedzi:

214

Jeśli programujesz Pythona przy użyciu Emacsa, prawdopodobnie powinieneś używać trybu Python. W trybie Pythona, po zaznaczeniu bloku kodu,

C-c >lub C-c C-l przesuwa region o 4 pola w prawo

C-c <lub C-c C-r przesuwa region o 4 pola w lewo

Jeśli potrzebujesz przesunąć kod o dwa poziomy wcięcia lub jakąś dowolną wartość, możesz poprzedzić polecenie argumentem:

C-u 8 C-c > przesuwa region o 8 pól w prawo

C-u 8 C-c < przesuwa region o 8 pól w lewo

Inną alternatywą jest użycie, M-x indent-rigidlyktóre jest związane z C-x TAB:

C-u 8 C-x TAB przesuwa region o 8 pól w prawo

C-u -8 C-x TAB przesuwa region o 8 pól w lewo

Przydatne są również polecenia prostokątów, które działają na prostokątach tekstu zamiast na wierszach tekstu.

Na przykład po zaznaczeniu obszaru prostokątnego

C-x r o wstawia puste miejsce, aby wypełnić prostokątny obszar (skutecznie przesuwając kod w prawo)

C-x r k zabija region prostokątny (skutecznie przesuwając kod w lewo)

C-x r twyświetla monit o podanie ciągu znaków, którym ma zostać zastąpiony prostokąt. Wpisanie C-u 8 <space>spowoduje wprowadzenie 8 spacji.

PS. W systemie Ubuntu, aby ustawić tryb Python jako domyślny tryb dla wszystkich plików .py, po prostu zainstaluj python-modepakiet.

unutbu
źródło
Dzięki temu działa idealnie. z Emacs22 czy tryb Pythona nie jest automatycznie włączony dla wszystkich plików .py? W każdym razie Cc> działa dobrze.
Vernon,
@Vernon: C-c >jest zdefiniowane w python-mode.el, więc myślę, że python-modepakiet musiał zostać zainstalowany gdzieś po drodze. Cieszę się, że to działa dla Ciebie.
unutbu
1
Cc> działa dobrze w Emacs 23.2 bez instalowania trybu Python, ponieważ działa z dostarczonym python.el
codeasone
@landstatic: Dzięki za informację. To sprawia, że ​​myślę, że być może wszystkie wymienione powyżej polecenia działają tak samo dla python-mode.el lub python.el?
unutbu
2
@redobot: C-c C-li C-c C-rmusi to być niestandardowe powiązanie, które sam skonfigurowałeś. Jeśli uruchomisz emacs -q(aby uruchomić emacsa bez ładowania pliku init), zobaczysz, że nie ma powiązania dla C-c C-llub C-c C-rw trybie Python.
unutbu
9

Oprócz tego indent-region, do którego jest C-M-\domyślnie mapowane , polecenia edycji prostokąta są bardzo przydatne w Pythonie. Oznacz region jako normalny, a następnie:

  • C-x r t( string-rectangle): zapyta o znaki, które chcesz wstawić w każdym wierszu; doskonale nadaje się do wstawiania określonej liczby spacji
  • C-x r k( kill-rectangle): usuwa region prostokąta; doskonały do ​​usuwania wgnieceń

Możesz także C-x r y( yank-rectangle), ale rzadko jest to przydatne.

Daniel Stutzbach
źródło
4

indent-regionzmapowany na C-M-\powinien załatwić sprawę.

Łukasz
źródło
3
To straszna rada. Nie można wywnioskować wcięć w Pythonie (ponieważ jest to składnia!), Więc region ident jest bezużyteczny.
Sam Clearman,
1

Używałem tej funkcji do obsługi wcięć i cofania wcięć:

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

A potem przypisuję go do skrótu klawiaturowego:

(global-set-key (kbd "s-[") 'unindent-dwim)
(global-set-key (kbd "s-]") (lambda () (interactive) (unindent-dwim -1)))
Singletoned
źródło
1

Jestem nowicjuszem Emacsa, więc ta odpowiedź prawdopodobnie graniczy z bezużytecznością.

Żadna z dotychczas wymienionych odpowiedzi nie obejmuje ponownego wcięcia literałów takich jak dictlub list. Np. M-x indent-regionLub M-x python-indent-shift-righti firma nie pomoże, jeśli wklejasz i wklejasz następujący dosłowny tekst i chcesz, aby został rozsądnie wprowadzony ponownie:

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

Wydaje się, że M-x indent-regionpowinienem zrobić coś rozsądnie python-mode, ale tak nie jest (jeszcze).

W konkretnym przypadku, w którym twoje literały są umieszczone w nawiasach, użycie klawisza TAB w odnośnych wierszach daje to, czego chcesz (ponieważ białe znaki nie odgrywają żadnej roli).

Więc to, co robiłem w takich przypadkach, to szybkie nagrywanie makra klawiatury, takiego <f3> C-n TAB <f4>jak F3, Ctrl-n (lub strzałka w dół), TAB, F4, a następnie wielokrotne użycie F4 do zastosowania makra pozwala zaoszczędzić kilka naciśnięć klawiszy. Albo możesz to zrobićC-u 10 C-x e aby zastosować go 10 razy.

(Wiem, że to nie brzmi jak dużo, ale spróbuj ponownie wprowadzić wcięcie 100 wierszy śmieciowego dosłownego bez pomijania strzałek w dół, a następnie idź w górę o 5 linii i powtarzaj rzeczy;)).

Obrabować
źródło
1

Używam następującego fragmentu. Na karcie, gdy zaznaczenie jest nieaktywne, wcina bieżący wiersz (jak zwykle); gdy zaznaczenie jest nieaktywne, wcina cały region w prawo.

(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
źródło
1

Wykonuj wcięcia interaktywnie.

  1. Wybierz region do wcięcia.
  2. Cx TAB.
  3. Użyj strzałek ( <-i ->), aby interakcyjnie wprowadzać wcięcia.
  4. Naciśnij Esctrzy razy, gdy skończysz z wymaganym wcięciem.

Skopiowano z mojego postu w: Wcięcie kilku wierszy w Emacsie

vineshvs
źródło
-2

Robię coś takiego uniwersalnie

;; 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
źródło
2
Ponieważ białe znaki są częścią składni w Pythonie, region wcięć w całym pliku jest złym pomysłem.
Daniel Stutzbach