มีวิธีในการ daisy chain .dir-locals.el หรือไม่


15

สมมติว่าฉันมีไดเรกทอรีพร้อมไฟล์เหล่านี้

/foo/bar/baz/.dir-locals.el
/foo/bar/.dir-locals.el
/foo/.dir-locals.el

เมื่อฉันไปสร้างไฟล์ใน/foo/bar/baz/ฉันต้องการเดซี่เชนพวกเขาด้วยกันที่/foo/.dir-locals.elใช้ก่อนแล้ว/foo/bar/.dir-locals.elจึง/foo/bar/baz/.dir-locals.el


หัวข้อที่เกี่ยวข้อง: ฉันจะมีวินาทีได้.dir-localsอย่างไร .
ด่าน

ไม่มีตัวเลือกที่จะทำอย่างนั้น (ฉันดูรหัสอย่างใกล้ชิด) แต่ควรเป็นไปได้ (เกือบจะแน่นอน) เป็นไปได้ด้วยรหัสพิเศษบางอย่าง ฉันก็มีประโยชน์เช่นกันดังนั้นฉันจึงอาจพิจารณาในเรื่องนี้ ...
Constantine

ด้วย elisp ทุกสิ่งเป็นไปได้ :)
Eric Johnson

คำตอบ:


7

จากคำตอบที่นี่เราทำโดยแนะนำhack-dir-local-variablesให้ค้นหาไดเรกทอรีหนึ่งและตรวจสอบโหลดว่า.dir-locals.elไฟล์นั้นสามารถอ่านได้ .dir-locals.elมันจะให้ไปขึ้นจนกว่าจะพบไดเรกทอรีที่ไม่มีอ่าน

ขึ้นอยู่กับค่าของwalk-dir-locals-upwardไฟล์ที่สามารถอ่านได้จากไดเรกทอรีปัจจุบันขึ้นหรือจากที่.dir-locals.elพบล่าสุดลง Downward เป็นค่าเริ่มต้นเพื่อให้ไดเรกทอรีย่อยสามารถปิดกั้นการตั้งค่าของผู้ปกครองได้

(defvar walk-dir-locals-upward nil
  "If non-nil, evaluate .dir-locals.el files starting in the
  current directory and going up. Otherwise they will be
  evaluated from the top down to the current directory.")

(defadvice hack-dir-local-variables (around walk-dir-locals-file activate)
  (let* ((dir-locals-list (list dir-locals-file))
         (walk-dir-locals-file (first dir-locals-list)))
    (while (file-readable-p (concat "../" walk-dir-locals-file))
      (progn
        (setq walk-dir-locals-file (concat "../" walk-dir-locals-file))
        (add-to-list 'dir-locals-list walk-dir-locals-file
                     walk-dir-locals-upward)
        ))
    (dolist (file dir-locals-list)
      (let ((dir-locals-file (expand-file-name file)))
        (message dir-locals-file)
        ad-do-it
        )))
  )

นี้ดูเหมือนว่าจะคาดหวังว่าทุกคนในไดเรกทอรีต้นไม้ (ถึงบางระดับขึ้นมาจากเส้นทางปัจจุบัน) .dir-locals.elมี มันจะทำงานถ้ามีต้นไม้ของไดเรกทอรีa/b/cและมีอยู่a/.dir-locals.elและa/b/c/.dir-locals.elแต่ไม่มีa/b/.dir-locals.el(สมมติว่าผมเข้ามาเยี่ยมชมa/b/c/foo.elและฉันต้องการตั้งค่าจากa/.dir-locals.elจะนำมาใช้)?
Constantine

1
ใช่นั่นคือสิ่งที่ฉันคิดเอาไว้ ชาวบ้านที่ขาดหายไปa/b/แบ่งโซ่ มันต้องหยุดที่ไหนสักแห่งและถ้าคุณต้องการมันต่อไปคุณสามารถเพิ่มไฟล์ dir-locals ที่ว่างเปล่าได้
erikstokes

3
BTW ฉันยินดีต้อนรับแพทช์สำหรับ Emacs เพื่อสนับสนุนการผูกมัดคนในพื้นที่ออกจากกล่อง
สเตฟาน

6

นี่คือวิธีที่แตกต่างในการทำเช่นนี้

ฉันกำหนดฟังก์ชันที่สร้างรายการของไดเรกทอรีทั้งหมดในลำดับชั้นไดเรกทอรีปัจจุบัน

(defun file-name-directory-nesting-helper (name previous-name accumulator)
  (if (string= name previous-name)
      accumulator                       ; stop when names stop changing (at the top)
      (file-name-directory-nesting-helper
       (directory-file-name (file-name-directory name))
       name
       (cons name accumulator))))

(defun file-name-directory-nesting (name)
  (file-name-directory-nesting-helper (expand-file-name name) "" ()))

ตัวอย่างอยู่ในลำดับ:

(file-name-directory-nesting "/foo/bar/baz/quux/foo.el")
;; => ("/" "/foo" "/foo/bar" "/foo/bar/baz" "/foo/bar/baz/quux" "/foo/bar/baz/quux/foo.el")

ตอนนี้ฉันสามารถเพิ่มคำแนะนำเพื่อhack-dir-local-variablesทำให้ "แกล้ง" ว่าเรากำลังเยี่ยมชมไฟล์ที่ด้านบนสุดของทรีใช้การตั้งค่าไดเรกทอรีท้องถิ่นจากนั้นลดระดับหนึ่งลงใช้การตั้งค่าอีกครั้งและอื่น ๆ

(defun hack-dir-local-variables-chained-advice (orig)
  "Apply dir-local settings from the whole directory hierarchy,
from the top down."
  (let ((original-buffer-file-name (buffer-file-name))
        (nesting (file-name-directory-nesting (or (buffer-file-name)
                                                  default-directory))))
    (unwind-protect
        (dolist (name nesting)
          ;; make it look like we're in a directory higher up in the
          ;; hierarchy; note that the file we're "visiting" does not
          ;; have to exist
          (setq buffer-file-name (expand-file-name "ignored" name))
          (funcall orig))
      ;; cleanup
      (setq buffer-file-name original-buffer-file-name))))

(advice-add 'hack-dir-local-variables :around
            #'hack-dir-local-variables-chained-advice)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.