Emacs จำนวนมากเยื้องสำหรับ Python


132

การทำงานกับ Python ใน Emacs หากฉันต้องการเพิ่มการลอง / ยกเว้นในบล็อกของโค้ดฉันมักจะพบว่าฉันต้องเยื้องบล็อกทั้งหมดทีละบรรทัด ใน Emacs คุณจะเยื้องบล็อกทั้งหมดพร้อมกันได้อย่างไร

ฉันไม่ใช่ผู้ใช้ Emacs ที่มีประสบการณ์ แต่เพียงแค่พบว่ามันเป็นเครื่องมือที่ดีที่สุดสำหรับการทำงานผ่าน ssh ฉันใช้ Emacs บนบรรทัดคำสั่ง (Ubuntu) ไม่ใช่ gui หากสิ่งนั้นสร้างความแตกต่าง


5
C-c >ถูกต้อง C-c <ซ้าย
ธ มฺโกวดา

คำตอบ:


213

หากคุณกำลังเขียนโปรแกรม Python โดยใช้ Emacs คุณน่าจะใช้ python-mode ด้วย python-mode หลังจากทำเครื่องหมายบล็อกรหัสแล้ว

C-c >หรือC-c C-l เลื่อนพื้นที่ 4 ภูมิภาคไปทางขวา

C-c <หรือC-c C-r เลื่อนพื้นที่ 4 ภูมิภาคไปทางซ้าย

หากคุณต้องการเปลี่ยนรหัสตามการเยื้องสองระดับหรือจำนวนเงินอนุญาโตตุลาการคุณสามารถนำหน้าคำสั่งด้วยอาร์กิวเมนต์:

C-u 8 C-c > เลื่อนพื้นที่ 8 พื้นที่ไปทางขวา

C-u 8 C-c < เลื่อนพื้นที่ 8 พื้นที่ไปทางซ้าย

อีกทางเลือกหนึ่งคือการใช้M-x indent-rigidlyซึ่งผูกพันกับC-x TAB:

C-u 8 C-x TAB เลื่อนพื้นที่ 8 พื้นที่ไปทางขวา

C-u -8 C-x TAB เลื่อนพื้นที่ 8 พื้นที่ไปทางซ้าย

นอกจากนี้ยังมีประโยชน์คือคำสั่งสี่เหลี่ยมผืนผ้าที่ทำงานกับข้อความสี่เหลี่ยมแทนที่จะเป็นบรรทัดข้อความ

ตัวอย่างเช่นหลังจากทำเครื่องหมายพื้นที่สี่เหลี่ยมแล้ว

C-x r o แทรกช่องว่างเพื่อเติมพื้นที่สี่เหลี่ยม (เลื่อนรหัสไปทางขวาอย่างมีประสิทธิภาพ)

C-x r k ฆ่าพื้นที่สี่เหลี่ยม (เปลี่ยนรหัสไปทางซ้ายอย่างมีประสิทธิภาพ)

C-x r tพร้อมต์ให้สตริงแทนที่สี่เหลี่ยมผืนผ้าด้วย การเข้าC-u 8 <space>จะต้องใส่ 8 ช่องว่าง

PS ด้วย Ubuntu เพื่อให้โหมด python เป็นโหมดเริ่มต้นสำหรับไฟล์. py ทั้งหมดเพียงแค่ติดตั้งpython-modeแพ็คเกจ


ขอบคุณที่ทำงานได้อย่างสมบูรณ์ ด้วย Emacs22 ไม่ได้เปิดโหมด python โดยอัตโนมัติกับไฟล์. py ทั้งหมดใช่หรือไม่ อย่างไรก็ตาม Cc> ใช้งานได้ดี
Vernon

@Vernon: C-c >ถูกกำหนดใน python-mode.el ดังนั้นฉันคิดว่าคุณต้องติดตั้งpython-modeแพ็คเกจไว้ที่ไหนสักแห่งระหว่างทาง ดีใจที่ได้ผลสำหรับคุณ
unutbu

1
Cc> ทำงานได้ดีใน Emacs 23.2 โดยไม่ต้องติดตั้ง python-mode เนื่องจากทำงานร่วมกับ python.el ที่ให้มา
codeasone

@landstatic: ขอบคุณสำหรับข้อมูล นั่นทำให้ฉันคิดว่าบางทีคำสั่งทั้งหมดที่ระบุไว้ข้างต้นใช้งานได้เหมือนกันสำหรับ python-mode.el หรือ python.el?
unutbu

2
@redobot: C-c C-lและC-c C-rต้องเป็นการผูกแบบกำหนดเองที่คุณตั้งขึ้นเอง หากคุณเรียกใช้emacs -q(เพื่อเรียกใช้ emac โดยไม่ต้องโหลดไฟล์ init) คุณจะเห็นว่าไม่มีการผูกสำหรับC-c C-lหรือC-c C-rในโหมด Python
unutbu

9

นอกจากนี้indent-regionซึ่งถูกแมปกับC-M-\ค่าเริ่มต้นแล้วคำสั่งแก้ไขสี่เหลี่ยมผืนผ้ายังมีประโยชน์มากสำหรับ Python ทำเครื่องหมายพื้นที่ตามปกติจากนั้น:

  • C-x r t( string-rectangle): จะแจ้งให้คุณป้อนอักขระที่คุณต้องการแทรกในแต่ละบรรทัด เหมาะสำหรับการแทรกช่องว่างจำนวนหนึ่ง
  • C-x r k( kill-rectangle): ลบพื้นที่สี่เหลี่ยมผืนผ้า เหมาะสำหรับการลบการเยื้อง

คุณยังสามารถC-x r y( yank-rectangle) ได้ แต่ก็ไม่ค่อยมีประโยชน์


4

indent-regionแมปC-M-\ควรทำเคล็ดลับ


3
นี่เป็นคำแนะนำที่แย่มาก ไม่สามารถอนุมานการเยื้อง Python ได้ (เนื่องจากเป็นไวยากรณ์!) ดังนั้นพื้นที่ระบุจึงไม่มีประโยชน์
Sam Clearman

1

ฉันใช้ฟังก์ชันนี้เพื่อจัดการการเยื้องและการยกเลิกการเยื้อง:

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

จากนั้นฉันกำหนดให้เป็นแป้นพิมพ์ลัด:

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

1

ฉันเป็น Emacs newb ดังนั้นคำตอบนี้มันอาจจะไร้ประโยชน์

ไม่มีคำตอบดังกล่าวเพื่อให้ห่างไกลครอบคลุมเรื่องการเยื้องของตัวอักษรเหมือนหรือdict listเช่นM-x indent-regionหรือM-x python-indent-shift-rightและ บริษัท จะไม่ช่วยถ้าคุณตัดและวางตัวอักษรต่อไปนี้และจำเป็นต้องเยื้องใหม่อย่างสมเหตุสมผล:

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

รู้สึกว่าM-x indent-regionควรทำอะไรอย่างสมเหตุสมผลpython-modeแต่ก็ยังไม่เป็นเช่นนั้น

สำหรับกรณีเฉพาะที่ตัวอักษรของคุณอยู่ในวงเล็บการใช้ TAB ในบรรทัดที่เป็นปัญหาจะได้รับสิ่งที่คุณต้องการ (เนื่องจากช่องว่างไม่มีบทบาท)

ดังนั้นสิ่งที่ฉันทำในกรณีเช่นนี้คือการบันทึกมาโครแป้นพิมพ์อย่างรวดเร็วเช่น<f3> C-n TAB <f4>ใน F3, Ctrl-n (หรือลูกศรลง), TAB, F4 แล้วใช้ F4 ซ้ำ ๆ เพื่อใช้มาโครสามารถบันทึกการกดแป้นพิมพ์ได้สองสามครั้ง หรือC-u 10 C-x eจะทา 10 ครั้งก็ได้

(ฉันรู้ว่ามันฟังดูไม่ค่อยออก แต่ลองเยื้องตัวอักษรขยะ 100 บรรทัดใหม่โดยไม่พลาดลูกศรลงจากนั้นต้องขึ้น 5 บรรทัดแล้วทำซ้ำ;))


1

ฉันใช้ข้อมูลโค้ดต่อไปนี้ บนแท็บเมื่อการเลือกไม่ทำงานมันจะเยื้องบรรทัดปัจจุบัน (ตามปกติ) เมื่อการเลือกไม่ทำงานมันจะเยื้องทั้งภูมิภาคไปทางขวา

(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

ทำการเยื้องแบบโต้ตอบ

  1. เลือกพื้นที่ที่จะเยื้อง
  2. Cx TAB.
  3. ใช้ลูกศร ( <-และ->) เพื่อเยื้องแบบโต้ตอบ
  4. กดEscสามครั้งเมื่อคุณเสร็จสิ้นการเยื้องที่ต้องการ

คัดลอกจากโพสต์ของฉันใน: เยื้องหลายบรรทัดใน Emacs


-2

ฉันทำอะไรแบบนี้ในระดับสากล

;; 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
เนื่องจากช่องว่างเป็นส่วนหนึ่งของไวยากรณ์ใน Python ดังนั้นการเยื้องขอบเขตของไฟล์ทั้งหมดจึงเป็นความคิดที่ไม่ดี
Daniel Stutzbach
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.