Indentasi massal Emacs untuk Python

132

Bekerja dengan Python di Emacs jika saya ingin menambahkan coba / kecuali pada blok kode, saya sering menemukan bahwa saya harus membuat indentasi seluruh blok, baris demi baris. Di Emacs, bagaimana Anda membuat indentasi seluruh blok sekaligus.

Saya bukan pengguna Emacs yang berpengalaman, tetapi hanya menemukan itu adalah alat terbaik untuk bekerja melalui ssh. Saya menggunakan Emacs pada baris perintah (Ubuntu), bukan sebagai gui, jika itu membuat perbedaan.

Vernon
sumber
5
C-c >untuk benar. C-c <untuk kiri
Thamme Gowda

Jawaban:

213

Jika Anda memprogram Python menggunakan Emacs, maka Anda mungkin harus menggunakan mode python. Dengan mode-python, setelah menandai blok kode,

C-c >atau C-c C-l menggeser wilayah 4 spasi ke kanan

C-c <atau C-c C-r menggeser wilayah 4 spasi ke kiri

Jika Anda perlu menggeser kode dengan dua tingkat indensi, atau jumlah arbiter, Anda dapat mengawali perintah dengan argumen:

C-u 8 C-c > menggeser wilayah 8 ruang ke kanan

C-u 8 C-c < menggeser wilayah 8 ruang ke kiri

Alternatif lain adalah menggunakan M-x indent-rigidlyyang terikat pada C-x TAB:

C-u 8 C-x TAB menggeser wilayah 8 ruang ke kanan

C-u -8 C-x TAB menggeser wilayah 8 ruang ke kiri

Juga berguna adalah perintah persegi panjang yang beroperasi pada persegi panjang teks, bukan pada baris teks.

Misalnya, setelah menandai wilayah persegi panjang,

C-x r o menyisipkan ruang kosong untuk mengisi wilayah persegi panjang (secara efektif menggeser kode ke kanan)

C-x r k membunuh wilayah persegi panjang (secara efektif menggeser kode ke kiri)

C-x r tmeminta string untuk menggantikan persegi panjang dengan. Memasuki C-u 8 <space>kemudian akan memasuki 8 spasi.

PS. Dengan Ubuntu, untuk menjadikan mode-python mode default untuk semua file .py, cukup instal python-modepaketnya.

unutbu
sumber
Terima kasih itu bekerja dengan sempurna. dengan Emacs22 bukankah mode-python diaktifkan secara otomatis dengan semua file .py? Bagaimanapun, Cc> berfungsi dengan baik.
Vernon
@Vernon: C-c >didefinisikan dalam python-mode.el, jadi saya pikir Anda harus menginstal python-modepaket di suatu tempat di sepanjang jalan. Senang itu berhasil untuk Anda.
unutbu
1
Cc> berfungsi dengan baik di Emacs 23.2 tanpa menginstal mode python karena bekerja dengan python.el yang disediakan
codeasone
@landstatic: Terima kasih atas informasinya. Itu membuat saya berpikir mungkin semua perintah yang tercantum di atas berfungsi sama untuk python-mode.el atau python.el?
unutbu
2
@redobot: C-c C-ldan C-c C-rharus merupakan binding khusus yang Anda buat sendiri Jika Anda menjalankan emacs -q(untuk menjalankan emacs tanpa memuat file init) Anda akan melihat tidak ada pengikatan untuk C-c C-latau C-c C-rdalam mode Python.
unutbu
9

Selain itu indent-region, yang dipetakan C-M-\secara default, perintah edit persegi panjang sangat berguna untuk Python. Tandai wilayah sebagai normal, lalu:

  • C-x r t( string-rectangle): akan meminta karakter yang ingin Anda masukkan ke setiap baris; bagus untuk memasukkan sejumlah ruang tertentu
  • C-x r k( kill-rectangle): menghapus wilayah persegi panjang; bagus untuk menghilangkan lekukan

Anda juga dapat C-x r y( yank-rectangle), tetapi itu jarang berguna.

Daniel Stutzbach
sumber
4

indent-regiondipetakan untuk C-M-\melakukan trik.

Łukasz
sumber
3
Ini saran yang mengerikan. Lekukan python tidak dapat disimpulkan (karena itu sintaks!) Jadi ident-region tidak berguna.
Sam Clearman
1

Saya telah menggunakan fungsi ini untuk menangani indentasi dan indentasi saya:

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

Dan kemudian saya menetapkan untuk pintasan keyboard:

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

Saya seorang pemula Emacs, jadi jawaban ini mungkin berbatasan dengan tidak berguna.

Tidak ada jawaban yang disebutkan sejauh ini mencakup lekukan kembali literal seperti dictatau list. Misalnya M-x indent-regionatau M-x python-indent-shift-rightdan perusahaan tidak akan membantu jika Anda telah memotong-dan-menempelkan literal berikut ini dan membutuhkannya untuk diindentasi ulang dengan masuk akal:

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

Rasanya seperti M-x indent-regionharus melakukan sesuatu yang masuk akal python-mode, tapi itu belum (belum) terjadi.

Untuk kasus khusus di mana literal Anda dikurung, menggunakan TAB pada baris tersebut mendapatkan apa yang Anda inginkan (karena spasi tidak memainkan peran).

Jadi apa yang telah saya lakukan dalam kasus seperti ini adalah dengan cepat merekam keyboard keyboard seperti <f3> C-n TAB <f4>pada F3, Ctrl-n (atau panah bawah), TAB, F4, dan kemudian menggunakan F4 berulang kali untuk menerapkan makro dapat menyimpan beberapa penekanan tombol. Atau bisa Anda lakukan C-u 10 C-x euntuk menerapkannya 10 kali.

(Saya tahu ini kedengarannya tidak terlalu banyak, tetapi coba inden indentasi ulang 100 baris sampah tanpa kehilangan panah bawah, dan kemudian harus naik 5 baris dan ulangi hal-hal;)).

rampok
sumber
1

Saya menggunakan cuplikan berikut. Pada tab ketika pilihan tidak aktif, itu indentasi garis saat ini (seperti biasanya); ketika pemilihan tidak aktif, itu indentasi seluruh wilayah ke kanan.

(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)
bodoh
sumber
1

Lakukan indentasi secara interaktif.

  1. Pilih wilayah yang akan diindentasi.
  2. Cx TAB.
  3. Gunakan panah ( <-dan ->) untuk indentasi interaktif.
  4. Tekan Esctiga kali saat Anda selesai dengan lekukan yang diperlukan.

Disalin dari posting saya di: Indent beberapa baris di Emacs

anggur
sumber
-2

Saya melakukan sesuatu seperti ini secara universal

;; 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
sumber
2
Karena spasi putih adalah bagian dari sintaksis dalam Python, indent-region pada seluruh file adalah ide yang buruk.
Daniel Stutzbach