วิธีสลับไปมาระหว่างสองตำแหน่งในบัฟเฟอร์


38

บางครั้งฉันพบว่าตัวเองสลับกันระหว่างสองฟังก์ชั่นที่ฉันแก้ไขร่วมกันบ่อยๆ ในสถานการณ์เหล่านี้มันน่าเบื่อและเจ็บปวดที่จะทำต่อC-s <functionname>เพื่อสลับไปยังฟังก์ชั่นอื่น ๆ แล้วหาที่ที่ฉันแก้ไขก่อนหน้านี้

ฉันจะตั้งค่าตัวทำเครื่องหมายแล้วข้ามไปมาระหว่างสองตำแหน่งในบัฟเฟอร์ได้อย่างง่ายดาย


3
คุณทำผิด คุณควรมีมุมมองแยกตามแนวตั้งเพื่อให้คุณเห็นทั้งสองฟังก์ชันในเวลาเดียวกัน
CaptainCodeman

8
ฉันไม่เห็นด้วยที่ OP กำลัง "ทำผิด" ในขณะที่หน้าต่างแบบแยกจะเป็นประโยชน์ OP ยังคงต้องข้ามไปมาระหว่างหน้าต่างเมื่อแก้ไขทั้งสองฟังก์ชัน นอกจากนั้นคำถามทั่วไปมากกว่ากรณีการใช้งานเฉพาะ: OP ต้องการให้สามารถข้ามไปยังตำแหน่งต่างๆในบัฟเฟอร์ได้อย่างรวดเร็ว คำตอบมากมายด้านล่างให้วิธีการที่เป็นประโยชน์มากมาย
แดน

@ แดนนั่นคือคนที่ยอดเยี่ยมและฉันเห็นด้วยกับคุณ แต่คำตอบของฉันไม่ได้มีไว้เพื่อแก้ปัญหาของเขา - เพียงเพื่อชี้ให้เห็นว่ามีวิธีอื่น
CaptainCodeman

4
@CaptainCodeman แต่ก็ดีแม้ว่าคำตอบของ T. Vernon ด้านล่างจะเป็นตัวเลือกแยกหน้าต่าง โปรดปฏิบัติต่อความคิดเห็นของฉันเป็นคำขอทั่วไปเพิ่มเติมสำหรับภาษาเชิงรุกในโพสต์
แดน

1
@CaptainCodeman คุณพูดถูก ฉันไม่ทราบว่า emacs รองรับการแยกมุมมองแนวตั้ง ดังนั้นฉันจึงยอมรับคำตอบที่ให้รายละเอียดเกี่ยวกับการใช้มุมมองการแบ่งตามแนวตั้งเหล่านี้
Vedaad Shakib

คำตอบ:


20

หน้าต่าง emacs

C-x 2จะเปิดอีกหน้าต่างหนึ่ง (= แยกเฟรม) ด้านล่างของเฟรมปัจจุบันที่แนบมากับบัฟเฟอร์เดียวกัน คุณสามารถย้ายจุดในหน้าต่างใดก็ได้โดยไม่กระทบกับสิ่งอื่น

C-x oคุณสามารถย้ายจากหน้าต่างหนึ่งไปยังอีกที่ใช้ ไลบรารีwindmoveในตัวมีฟังก์ชันบางอย่างที่ทำให้การนำทางระหว่าง windows ง่ายขึ้น

หากวิธีนี้เหมาะกับคุณคุณอาจต้องการที่จะมีลักษณะที่บัฟเฟอร์ทางอ้อม

ป้อนคำอธิบายรูปภาพที่นี่


บางทีคุณควรเพิ่มอีกสองสามบรรทัดเกี่ยวกับการใช้บัฟเฟอร์ทางอ้อม: มันมีประโยชน์มากกว่า (และซับซ้อนกว่าเล็กน้อย) กว่าการใช้เพียงหน้าต่างอื่น
ffevotte

@ Francesco ฉันเห็นสิ่งที่คุณหมายถึงตอนนี้ (พร้อมคำตอบอื่น ๆ เกี่ยวกับบัฟเฟอร์ทางอ้อม) แน่นอนว่าเป็นตัวเลือกที่ใช้งานง่ายมากเกินไป นั่นไม่ใช่การใช้งานที่ฉันมีอยู่ในใจ: การใช้บัฟเฟอร์ทางอ้อมของฉันไม่ได้แทนที่การใช้หน้าต่างอื่น แต่มันช่วยให้สามารถเปลี่ยนมุมมองด้วยการ จำกัด ให้แคบลงได้ ฉันจะเพิ่มคำสองสามคำลงในคำตอบเมื่อฉันหาเวลา
ต. Verron

56

ลงทะเบียน:

C-xrSPCวิ่งpoint-to-register
C-xrjวิ่งjump-to-register

พิมพ์อักขระใด ๆ เพื่อระบุการลงทะเบียนเมื่อได้รับแจ้ง 1

ที่คั่นหน้า:

C-xrmวิ่งbookmark-set
C-xrbวิ่งbookmark-jump

แหวนมาร์ค:

C-SPCC-SPCผลักตำแหน่งปัจจุบันไปยังวงแหวนทำเครื่องหมาย (โดยไม่ปล่อยให้ทำงาน)
C-uC-SPCดึงแหวนมาร์คกระโดดไปยังตำแหน่งก่อนหน้า คุณสามารถใช้สิ่งนี้ซ้ำ ๆ เพื่อเลื่อนดูวงแหวนทั้งหมด

โปรดทราบว่าคำสั่งบางคำสั่ง (โดยเฉพาะคำสั่งที่มีแนวโน้มว่าจะย้ายคุณในระยะห่างที่ไม่ทราบหรือโดยพลการจากตำแหน่งเดิมของคุณ) จะผลักไปยังวงแหวนเครื่องหมายโดยอัตโนมัติเพื่อให้คุณสามารถใช้C-uC-SPCเพื่อกลับมาภายหลังได้ ซึ่งรวมถึงisearchดังนั้นหลังจากใช้C-sไปที่ไหนสักแห่งคุณสามารถกระโดดกลับมาอีกครั้งได้อย่างง่ายดาย

แลกเปลี่ยนจุดและเครื่องหมาย:

และในฐานะที่เป็นความคิดเห็นของ Tu Do การC-xC-xวิ่งexchange-point-and-markที่มีประโยชน์มากสำหรับการกระโดดข้ามสถานที่สองแห่ง นอกจากนี้ยังเปิดใช้งานเครื่องหมาย / ภูมิภาค แต่คุณสามารถใช้C-SPCเพื่อล้างการเน้นได้


1หากคุณใช้ประโยชน์จากฟังก์ชันการลงทะเบียนใน elisp ให้ใช้สัญลักษณ์ที่ไม่ขัดแย้งกันสำหรับชื่อแทนที่จะเป็นอักขระเพื่อที่คุณจะไม่สามารถขัดแย้งกับการลงทะเบียนแบบโต้ตอบ (เว้นแต่แน่นอนคุณต้องการทำเช่นนั้น ที่).


2
คุณควรเพิ่มC-x C-xเช่นกันเนื่องจากสามารถข้ามไปมาระหว่างสองตำแหน่งได้ C-u C-SPCปรากฏแหวนทำเครื่องหมายและดำเนินการอีกครั้งจะย้ายจุดอื่น
Tu Do

18

นอกจากคำตอบของ phils แล้วยังมีตัวเลือกเพิ่มเติม:

  • helm-all-mark-ring : ช่วยให้คุณสามารถดูเนื้อหาของเครื่องหมายทั้งในระดับท้องถิ่นและระดับโลกในส่วนติดต่อที่เป็นมิตรดังนั้นคุณจึงสามารถย้อนกลับไปยังตำแหน่งที่คุณเคยอยู่ C-SPC C-SPCคุณสามารถผลักดันเครื่องหมายด้วย การสาธิต:

หางเสือทั้งหมดเครื่องหมายแหวน

  • helm-semantic-or-imenu : แสดงรายการคำจำกัดความที่มีอยู่ทั้งหมดในไฟล์ปัจจุบัน หากเคอร์เซอร์อยู่ในคำจำกัดความเมื่อเปิดใช้งานปากกาเน้นข้อความจะเป็นการเลือกคำจำกัดความดังกล่าว

  • sr-speedbar : ไฟล์เบราว์เซอร์ที่แสดงคำจำกัดความของมันในแต่ละไฟล์ มันคล้ายกับเค้าร่างต้นไม้ใน IDE


9

นอกเหนือจากการลงทะเบียนและเครื่องหมาย (ดูคำตอบของ @ phils เกี่ยวกับทั้งสองและอื่น ๆ ของฉัน, คำตอบที่หยั่งรู้เกี่ยวกับเครื่องหมาย), ที่คั่นหน้า , โดยเฉพาะอย่างยิ่งที่คั่นหน้าอัตโนมัติหรือที่คั่นหน้าจะมีประโยชน์สำหรับสิ่งนี้ คุณต้องมี Library Bookmark +สำหรับประเภทบุ๊คมาร์คพิเศษเหล่านี้

  • autonamedบุ๊กเป็นสิ่งหนึ่งที่คุณไม่จำเป็นต้องไปที่ชื่อ การสร้างและลบทำได้อย่างรวดเร็วเพียงกดคีย์ รหัสเดียวกันจะสร้างหรือลบที่คั่นหน้าตรงจุด (โดยค่าเริ่มต้นสิ่งนี้ถูกผูกไว้C-x p RETแต่คุณสามารถใช้คีย์ใด ๆ ได้แน่นอน)

  • บุ๊กมาร์กอัตโนมัติที่มีชื่อเหมือนบุ๊กมาร์กทั่วไปถาวร แต่คุณสามารถลบได้โดยอัตโนมัติ

  • นอกจากนี้คุณยังสามารถสร้างบุ๊คมาร์คชั่วคราวหรือทำบุ๊คมาร์คที่มีอยู่ชั่วคราว ตัวอย่างเช่นคุณสามารถเลือกที่จะทำให้บุ๊กมาร์กอัตโนมัติมีชื่อเป็นการชั่วคราวโดยอัตโนมัติ

  • คุณสามารถวนรอบอย่างรวดเร็วระหว่างชุดบุ๊คมาร์คที่กำหนด ตัวอย่างเช่นในการวนรอบระหว่างบุ๊กมาร์กอัตโนมัติให้ใช้คำสั่งbmkp-next-autonamed-bookmark-repeatและbmkp-previous-autonamed-bookmark-repeat(ผูกเข้ากับคีย์)

  • คุณสามารถเน้นตำแหน่งบุ๊กมาร์กได้หลายวิธีดังนั้นจึงง่ายต่อการค้นหาตำแหน่ง


7

เกี่ยวกับบัฟเฟอร์ทางอ้อมที่กล่าวถึงในคำตอบที่ยอมรับ ...

M-x clone-indirect-bufferจะสร้างบัฟเฟอร์ทางอ้อมสำหรับบัฟเฟอร์ปัจจุบัน ชื่อของบัฟเฟอร์ใหม่จะมีการเพิ่ม '<2>' (หรือมากกว่าถ้าคุณมีชื่อบัฟเฟอร์ที่ซ้ำกันอยู่แล้ว) บัฟเฟอร์ใหม่ถูกเปิดในหน้าต่างใหม่ คุณสามารถสลับกลับไปที่หน้าต่างเดียวใช้หรือC-x 0C-x 1

ด้วยM-x winner-modeคุณสามารถสลับระหว่างสองตำแหน่งได้อย่างง่ายดาย C-c <left>/ M-x winner-undoและC-c <right>/ M-x winner-redoสลับระหว่างการกำหนดค่าหน้าต่าง ในกรณีนี้การกำหนดค่าจะเป็นตำแหน่งในบัฟเฟอร์สองตัวที่ดูไฟล์เดียว

หมายเหตุ: winner-undoและwinner-redoฟังก์ชั่นการทำงานในรายการของการกำหนดค่า หากการกำหนดค่ามีการเปลี่ยนแปลงเช่นจุดย้ายการกำหนดค่าปัจจุบันจะกลายเป็นส่วนหัวของรายการและwinner-redoไม่ถูกต้องในกรณีนี้winner-undoจะนำตำแหน่งก่อนหน้ากลับมา

สำหรับสถานการณ์ของ OP สิ่งนี้นำไปสู่กระบวนการต่อไปนี้

  1. เปิดโหมดผู้ชนะ M-x winner-mode
  2. เยี่ยมชมไฟล์ (ชื่อไฟล์: File1.txt, ชื่อบัฟเฟอร์: File1.txt)
  3. M-x clone-indirect-buffer (ชื่อบัฟเฟอร์ทางอ้อมใหม่: File1.txt <2>)
  4. ทำให้หน้าต่างปัจจุบันเป็นหน้าต่างเดียว C-x 1
  5. ค้นหาสถานที่แก้ไขก่อนทำการเปลี่ยนแปลง
  6. สลับไปที่ไฟล์การเยี่ยมชมบัฟเฟอร์ดั้งเดิมC-x b(ค่าเริ่มต้นจะเป็นบัฟเฟอร์ดั้งเดิมยกเว้นว่ามีการสลับไปใช้บัฟเฟอร์อื่นที่เกิดขึ้นตั้งแต่ขั้นตอนที่ 3) สิ่งนี้จะสร้างการกำหนดค่าใหม่สำหรับผู้ชนะเพื่อเปลี่ยนกลับเป็น
  7. ค้นหาสถานที่แก้ไขทางเลือกทำการเปลี่ยนแปลง

สวิตช์ไปยังตำแหน่งแก้ไขก่อนหน้า (การกำหนดค่าหน้าต่าง) ขึ้นอยู่กับว่ามีการเปลี่ยนแปลงการกำหนดค่าหน้าต่างระหว่างสวิตช์หรือไม่

  • หากมีการเปลี่ยนแปลงสลับใช้/C-c <left>M-x winner-undo
  • หากไม่มีการเปลี่ยนแปลงจะทำการสลับใช้C-c <left>/ M-x winner-undoสำหรับย้อนกลับและC-c <right>/ M-x winner-redoเพื่อส่งต่อ

การเปลี่ยนแปลงเป็นอย่างอื่นกว่าอีกหรือwinner-undowinner-redo


3

ถ้าคุณใช้evil-modeเป็นกลุ่มเลเยอร์แล้วC-oและC-iจะทำงานเหมือนเดิม

พวกเขาเรียกใช้คำสั่ง/evil-jump-backward ข้ามไปยังตำแหน่งที่เก่ากว่าในรายการข้ามซึ่งถูกตั้งค่าโดยอัตโนมัติ (เครื่องหมายถูกตั้งค่าตามคำสั่งการเคลื่อนไหว) ย้อนกลับ นอกจากนี้เรายังสามารถใช้หลังจากแทน ดังนั้นการใช้ทั้งสองฟังก์ชั่นจะนำคุณกลับไปกลับมาในบัฟเฟอร์ปัจจุบันของคุณforwardC-oC-iTABC-oC-i

หากคุณต้องการให้ฟีเจอร์นี้เป็นบัฟเฟอร์ข้ามหน้าให้ดูevil-jumpers: http://melpa.org/#/evil-jumper

«
evil-jumper เป็น add-on สำหรับโหมดร้ายซึ่งแทนที่การใช้งานของรายการกระโดดซึ่งมันเลียนแบบอย่างใกล้ชิดกับพฤติกรรมของ Vim โดยเฉพาะมันจะกระโดดข้ามขอบเขตบัฟเฟอร์และฟื้นฟูบัฟเฟอร์ที่ตายแล้วหากจำเป็น รายการข้ามยังสามารถเก็บไว้ในไฟล์และเรียกคืนระหว่างเซสชันได้ »

หมายเหตุ: ฉันเรียนรู้เกี่ยวกับวิกินี้


สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม หากต้องการวิจารณ์หรือขอคำชี้แจงจากผู้แต่งโปรดแสดงความคิดเห็นใต้โพสต์ของพวกเขา
แดน

1
D'oh และจากความคิดเห็นอัตโนมัตินั้นจริง ๆ แล้วฉันหมายความว่าคำตอบนั้นดูเหมือนว่าตั้งใจจะแสดงความคิดเห็นในคำตอบอื่น หากคุณต้องการให้สิ่งนี้เป็นคำตอบในสิทธิของตนเองคุณสามารถขยายสิ่งเล็กน้อยC-oและC-iทำอะไรได้บ้าง?
แดน

คุณถูก ! เสร็จแล้ว
Ehvince

2

หากคุณใช้Iciclesคุณสามารถเลื่อนไปมาระหว่างตัวทำเครื่องหมายในmark-ringบัฟเฟอร์แต่ละอันหรือglobal-mark-ring(ซึ่งมีเครื่องหมายเดียวในแต่ละบัฟเฟอร์)

คุณทำได้โดยใช้คำสั่งหลายคำสั่ง C-- C-SPC (สำหรับบัฟเฟอร์mark-ring) หรือC-- C-x C-SPC(สำหรับglobal-mark-ring) หลังจากกดปุ่มครั้งเดียวคุณจะใช้ปุ่มIcicles cycling ปกติฯลฯ เพื่อเลื่อนไปมาระหว่างเครื่องหมายของวงแหวน

(คีย์เดียวกันโดยไม่มีคำนำหน้า arg ตั้งเครื่องหมาย ( set-mark-command) และ pop เครื่องหมายสากล ( pop-global-mark) ตามลำดับเช่นเดียวกับที่ทำใน vanilla Emacs)

ข้อความของบรรทัดของแต่ละตัวทำเครื่องหมายถูกใช้เป็นตัวเลือกที่สมบูรณ์ ขณะที่คุณพิมพ์อินพุต minibuffer ของคุณจะ จำกัด ผู้สมัครให้ตรงกับผู้ที่ตรงกัน (เช่นการจับคู่สตริงย่อยหรือ regexp) คุณสามารถวนรอบเครื่องหมายที่ตรงกันหรือไปที่ใดก็ได้โดยตรง คุณสามารถเปลี่ยนลำดับการจัดเรียง ( C-,) สำหรับการขี่จักรยาน


2

ความเป็นไปได้ที่น้อยที่สุด แต่มักเป็นประโยชน์ - เมื่อคุณต้องการฟังก์ชั่นอื่น ๆ - กำลังตั้งค่า

(setq scroll-preserve-screen-position t)

ซึ่งจะนำคุณกลับไปที่ตำแหน่งเคอร์เซอร์ของคุณเริ่มต้นที่แน่นอนเมื่อมีการสลับระหว่างและC-vM-v


1

evil-modeดำเนินเครื่องหมายที่เป็นกลุ่มสไตล์ คุณสามารถตั้งเครื่องหมายด้วย ( mนั่นคือevil-set-marker) และข้ามไปที่เครื่องหมายด้วย backtick `( evil-goto-mark) หรือไปที่บรรทัดของเครื่องหมาย'( evil-goto-mark-line)

ดังนั้นคุณสามารถสร้างเครื่องหมาย "a" ที่ตำแหน่งแรกด้วยmaสร้างเครื่องหมาย "b" ที่ตำแหน่งที่สองด้วยmaจากนั้น'aเพื่อข้ามไปยังเครื่องหมาย "a" และ'bเพื่อข้ามไปยังเครื่องหมาย "b"


1

ใช้ imenu และด้านล่างรหัส

(defvar rimenu-position-pair nil "positions before and after imenu jump")
(add-hook 'imenu-after-jump-hook
          (lambda ()
            (let ((start-point (marker-position (car mark-ring)))
                  (end-point (point)))
              (setq rimenu-position-pair (list start-point end-point)))))

(defun rimenu-jump ()
  "jump to the closest before/after position of latest imenu jump"
  (interactive)
  (when rimenu-position-pair
    (let ((p1 (car rimenu-position-pair))
          (p2 (cadr rimenu-position-pair)))

      ;; jump to the far way point of the rimenu-position-pair
      (if (< (abs (- (point) p1))
             (abs (- (point) p2)))
          (goto-char p2)
          (goto-char p1))
      )))

1

ในช่วง 20 ปีที่ผ่านมาฉันใช้อัญมณีสองเม็ดนี้:

(defun ska-point-to-register ()
  "Store cursorposition _fast_ in a register. Use ska-jump-to-register
to jump back to the stored position."
  (interactive)
  (point-to-register 8))

(defun ska-jump-to-register ()
  "Switches between current cursorposition and position
that was stored with ska-point-to-register."
  (interactive)
  (let ((tmp (point-marker)))
    (jump-to-register 8)
    (set-register 8 tmp)))

ฉันผูกมันไว้กับ C- และ C-, ตามลำดับและใช้มันอย่างต่อเนื่องโดยไม่ทราบอีกต่อไป

ใช่ลงทะเบียนและเครื่องหมายและอื่น ๆ มีความยืดหยุ่นและมีประสิทธิภาพมากขึ้น แต่ก็ยังเป็นหนึ่งในผู้ช่วยเล็ก ๆ เหล่านั้นอย่างรวดเร็วที่ทำให้ฉันเป็นไปไม่ได้ที่จะเปลี่ยนไปใช้บรรณาธิการอื่น ๆ


1
ว้าวคุณใช้มันมานานกว่าที่ฉันเคยมีมา
Vedaad Shakib

ฉันเดาว่าสิ่งนี้จะไม่เกิดขึ้นในโลกของ Node หรือ Visual Studio Code แต่ใครจะรู้ว่า ... :-) ดีใจที่เห็นหนุ่มสาวที่ฉลาดและยังคงเก็บ Emacs อยู่ โอ้และฉันยังไม่ได้ 50 ;-)
Stefan Kamphausen

นี่มันสุดยอดมาก ฉันพยายามหาวิธีสลับระหว่างสองตำแหน่งโดยพลการโดยเปิดใช้งานโหมด transient-mark-mode และนี่ช่วยแก้ปัญหาได้ดีจริงๆ :) ขอบคุณ
PlagueHammer

0

นอกจากนี้คุณยังสามารถใช้ประโยชน์จากมาโครได้เนื่องจากสามารถผูกเข้ากับปุ่มที่สะดวกได้อย่างรวดเร็ว

ยกตัวอย่างเช่นบันทึกกระโดดไปที่ตำแหน่ง N โดยใช้และกำหนดให้กับปุ่ม<F3> M-g g N <F4> F5 C-x C-k b <F5>จากนั้นทำเช่นเดียวกันกับตำแหน่ง M และ F6 จากนี้ไปคุณสามารถสลับ F5 และ F6 เพื่อข้ามระหว่าง N และ M

ได้ง่ายเนื่องจาก<F4>รันครั้งสุดท้ายบันทึกแมโครและ<C-u> F4ติดกับคนสุดท้ายที่คุณสามารถข้ามกุญแจสำคัญที่มีผลผูกพันและขั้นตอนอื่นเพียงแค่ตำแหน่งที่ใช้และ<F4><C-u> F4


<C-x> 4 cเป็นไปได้อีกค่อนข้างรุนแรงคือการสร้างบัฟเฟอร์ทางอ้อมในหน้าต่างอื่นด้วย บัฟเฟอร์นี้มีเนื้อหาเหมือนกัน แต่อาจมีตำแหน่งจุดที่แตกต่างกัน ตอนนี้เพียงสลับไปมาระหว่างหน้าต่างด้วย<C-x> oวิธีปกติ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.