ฉันจะแทรกต้นแบบใน foo.h จาก foo.c โดยอัตโนมัติได้อย่างไร


11

สมมติว่าฉันกำลังเขียนโปรแกรม C ในไฟล์ foo.c:

int add_numbers(int x, int y, int z) {
    // Very complex implementation here.
    return x + y + z;
}

ฉันต้องการคำสั่งที่จะแทรกฟังก์ชั่นต้นแบบที่สอดคล้องกันใน foo.h:

int add_numbers(int x, int y, int z);

มีโซลูชั่น Emacs ที่มีอยู่สำหรับสิ่งนี้หรือไม่?

คำตอบ:


9

UPDATE : ฉันสร้างแพ็คเกจSemantic Refactorซึ่งแก้ปัญหานี้ได้อย่างสมบูรณ์และอีกมากมาย คุณสามารถดูการสาธิตเพื่อดูว่ามันทำงานอย่างไร ข้อความที่เหลืออยู่ของคำตอบนี้หลังจากประโยคนี้เก่าและวางไว้ที่นั่นเพื่อเหตุผลทางประวัติศาสตร์เท่านั้น

คำตอบเดิม :

คุณสามารถใช้senator-copy-tagสำหรับการคัดลอกฟังก์ชั่นลายเซ็นที่ถูกต้องแล้ววางกลับในไฟล์ต้นฉบับของคุณ senator-copy-tagและคำสั่ง Senator จะพร้อมใช้งานเมื่อคุณเปิดใช้งานsemantic-mode:

(semantic-mode 1)

Semantic เป็นแพ็คเกจในตัวของ Emacs

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

ฉันส่งประชาสัมพันธ์เพื่อEmacs Refactor รหัสเต็มถ้าคุณต้องการที่จะลองโดยไม่ต้องรอการประชาสัมพันธ์: คลิกที่นี่

นี่คือตัวอย่าง (เริ่มต้นเมื่อคุณเห็นSTART DEMOที่ด้านล่าง):

กระสุนปืนความหมายแทรกฟังก์ชั่นต้นแบบ

คุณสามารถใช้วุฒิสมาชิกเพียงเพื่อคัดลอกและฟังก์ชั่นต้นแบบ ตราบใดที่มีจุดอยู่ภายในฟังก์ชันของลายเซ็นหรือตัวฟังก์ชันให้เรียกใช้senator-copy-tagซึ่งถูกผูกไว้กับC-c , M-wค่าเริ่มต้นมันจะคัดลอกฟังก์ชันทั้งหมด: ทั้งลายเซ็นและเนื้อความ อย่างไรก็ตามคุณสามารถวางเฉพาะลายเซ็นได้หากคุณต้องการโดยเรียกใช้คำสั่งsenator-yank-tagซึ่งถูกผูกไว้C-c , C-yโดยค่าเริ่มต้น กดC-yวางลายเซ็นของฟังก์ชั่นทั้งหมดพร้อมกับร่างกายของมัน senator-copy-tagแม้ใช้งานกับฟังก์ชันลายเซ็นที่ขยายในหลายบรรทัดเช่นนี้

void 
func(int a,
     int b, 
     int c)
{
    .....
}

แม้ว่าวิธีการนี้จะไม่แทรกลงในบัฟเฟอร์โดยตรงด้วยชื่อเดียวกัน แต่จะมีประโยชน์มากกว่าในกรณีอื่น ๆ กรณีการใช้งานของคุณใช้งานได้หากคุณมีสองไฟล์ในไดเรกทอรีเดียวกันและมีชื่อเดียวกัน แต่มีนามสกุลต่างกัน จะเกิดอะไรขึ้นถ้าการประกาศฟังก์ชันและนิยามฟังก์ชันต้องอยู่ในไฟล์ต่าง ๆ ที่มีชื่อต่างกัน?

EDIT2 : นี่คือตัวอย่างสำหรับการแทรกฟังก์ชันต้นแบบอย่างชาญฉลาดโดยใช้แท็ก Semantic ขณะนี้คุณสามารถแทรกตามตำแหน่งสัมพัทธ์ ("ก่อนหน้า" และ "หลัง") ของแท็ก Semantic ระดับบนสุดเท่านั้น ฉันจะปรับปรุงให้กับผู้ใช้ให้เพื่อให้สามารถใส่ในสถานที่ใดที่แท็กความหมายที่มีอยู่กับตำแหน่งอื่น ๆ (เช่นเมื่อแท็กเป็นClassก็ควรมีตำแหน่งเพิ่มเติม: public, projectedและprivate) ตัวอย่างเริ่มต้นเมื่อคุณเห็นSTART DEMOที่ด้านล่าง:

กระสุนปืนความหมายแทรกฟังก์ชัน prototype2

โบนัส : ถ้าคุณต้องการที่จะสร้างรายการของคำนิยามของฟังก์ชั่นที่ว่างเปล่าใน.cppไฟล์จากไฟล์ส่วนหัวใช้สมาชิก functions.el แต่เร็ว ๆ นี้ฉันจะแทนที่ด้วย Semantic + Projectile


3

คำสั่งต่อไปนี้ควรทำ มันผ่านการทดสอบของฉันและไม่มีการพึ่งพาภายนอก

(defun endless/copy-proto-to-header-file ()
  (interactive)
  (save-excursion
    ;; c-mode's `beginning-of-defun' should be robust enough.
    (beginning-of-defun)
    (let ((l (point)))
      (search-forward-regexp " *{")
      (let ((proto (buffer-substring l (match-beginning 0))))
        (ff-find-other-file)
        ;; If other file is already open, we don't want to move point.
        (save-excursion
          (goto-char (point-max))
          ;; Do some more movement here if you want.
          (insert "\n" proto ";"))))))

2

ฉันคิดว่าสิ่งต่อไปนี้ควรใช้งานได้

(defun c-copy-function-signature-to-header ()
  (interactive)
  (save-excursion
    (let ((last-point -1))
      (while (/= (point) last-point)
        (setq last-point (point))
        (sp-backward-up-sexp))
      (kill-ring-save (point) (line-beginning-position))
      (ff-find-other-file)
      (yank)
      ;; clean whitespace between closing paren and opening curly 
      (delete-trailing-whitespace
        (line-beginning-position)
        (line-end-position))
      (insert ";")))

สิ่งนี้ต้องใช้smartparensแม้ว่าคุณอาจแฮ็คสำเนาของคุณเองsp-backward-up-sexpหากไม่สามารถยอมรับได้

นอกจากนี้โปรดทราบว่าสิ่งนี้จะใส่ส่วนหัวในทุกที่ที่คุณออกจากส่วน(point)ท้ายในส่วนหัว เนื่องจากคุณไม่ได้ระบุตำแหน่งที่คุณต้องการฉันคิดว่านี่น่าจะดีที่สุด แน่นอนถ้าคุณต้องการให้ผนวกที่ท้ายที่สุดแล้วคุณสามารถใส่ก่อน(end-of-buffer) (yank)แน่นอนว่าคุณสามารถเพิ่มสิ่งที่นักเล่นชื่นชอบเช่นการสร้างบรรทัดใหม่ใกล้กับจุดและดึงที่นั่น แต่ขึ้นอยู่กับรสนิยมของคุณ

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