Kuruluş modunda kaynak dosyaları eklerken başlangıç ​​ve bitiş satırlarını otomatik olarak nasıl hesaplayabilirim?


10

Belgelerimde aşağıdakiler var:

#+INCLUDE: "code/basic.sv" :src systemverilog :lines "14-117"

Burada 14 numaralı hat sahip olduğum yer class basic extends ..ve 116 numaralı hat sahip olduğum yer endclass.

14 ve 117 (= 116 + 1) sayılarını otomatik olarak eklemenin bir yolu var mı code/basic.sv?


Yani her zaman sınıftan uç sınıfa geçmesini mi istiyorsunuz?
Malabarba

1
Hayır. Bu bir örnekti. Başlangıç ​​ve bitiş çizgileri için normal ifade sağlayabileceğim bir çözüm düşünüyorum. Bir şey bir işlevi değerlendirirorg-include-src(FILE, LANGUAGE, REGEX_BEGIN, REGEX_END)
Kaushal Modi

Bunun bir yolu, dahil edilen dosyaya bir çeşit benzersiz işaretleyici (başlangıç ​​sonu) yerleştirmek ve bunları org-export-before-processing-hooksatır numaraları için önişlemek için bağlanacak bir işlevle bulmaktır . Başka bir yol sadece org posta listesine bir özellik istek posta göndermek :)
kindahero

Yanıtlar:


8

İşte başka bir seçenek. Bu, düzenli ifadeleri dahil etme temelinde özelleştirmenize izin verir. Uzantı tabanlı tanımlarla sınırlı olmadığınız için bazı iş akışlarına daha uygun olmalıdır.

Kullanmak

Kuruluş dosyanızda aşağıdakine benzer bir şey yapın. ( :linesAnahtar kelime isteğe bağlıdır)

#+INCLUDE: "code/my-class.sv" :src systemverilog :range-begin "^class" :range-end "^endclass" :lines "14-80"

İşlev "my-class.sv" adresini ziyaret eder ve bu iki normal ifadeyi arar ve ardından :linesanahtar kelimeyi eşleme sonucuna göre günceller .

Eğer :range-begineksik, aralık olacak "-80".
Eğer :range-endeksik, aralık olacak "14-".

Kod

(add-hook 'before-save-hook #'endless/update-includes)

(defun endless/update-includes (&rest ignore)
  "Update the line numbers of #+INCLUDE:s in current buffer.
Only looks at INCLUDEs that have either :range-begin or :range-end.
This function does nothing if not in org-mode, so you can safely
add it to `before-save-hook'."
  (interactive)
  (when (derived-mode-p 'org-mode)
    (save-excursion
      (goto-char (point-min))
      (while (search-forward-regexp
              "^\\s-*#\\+INCLUDE: *\"\\([^\"]+\\)\".*:range-\\(begin\\|end\\)"
              nil 'noerror)
        (let* ((file (expand-file-name (match-string-no-properties 1)))
               lines begin end)
          (forward-line 0)
          (when (looking-at "^.*:range-begin *\"\\([^\"]+\\)\"")
            (setq begin (match-string-no-properties 1)))
          (when (looking-at "^.*:range-end *\"\\([^\"]+\\)\"")
            (setq end (match-string-no-properties 1)))
          (setq lines (endless/decide-line-range file begin end))
          (when lines
            (if (looking-at ".*:lines *\"\\([-0-9]+\\)\"")
                (replace-match lines :fixedcase :literal nil 1)
              (goto-char (line-end-position))
              (insert " :lines \"" lines "\""))))))))

(defun endless/decide-line-range (file begin end)
  "Visit FILE and decide which lines to include.
BEGIN and END are regexps which define the line range to use."
  (let (l r)
    (save-match-data
      (with-temp-buffer
        (insert-file file)
        (goto-char (point-min))
        (if (null begin)
            (setq l "")
          (search-forward-regexp begin)
          (setq l (line-number-at-pos (match-beginning 0))))
        (if (null end)
            (setq r "")
          (search-forward-regexp end)
          (setq r (1+ (line-number-at-pos (match-end 0)))))
        (format "%s-%s" l r)))))

2
Bu harika! Şimdi bunu aynı dosyadan birden fazla parçacığı vermek için kullanabilirim. Pasaj 1: #+INCLUDE: "code/basic.sv" :src systemverilog :range-begin "// Example 1" :range-end "// End of Example 1". Pasaj 2: #+INCLUDE: "code/basic.sv" :src systemverilog :range-begin "// Example 2" :range-end "// End of Example 2". İcra kusursuz! Bunu bu kadar çabuk uyguladığınız için teşekkürler !
Kaushal Modi

5

Düşünebileceğim en iyi yol, bu sayıları dışa aktarmadan hemen önce veya değerlendirmeden önce güncellemektir.

Güncelleyici

Bu, arabellekten geçen işlevdir. Bir anahtara bağlayabilir veya bir kancaya ekleyebilirsiniz. Aşağıdaki kod , dosyayı her kaydettiğinizde güncellenir , ancak kullanım durumunuz farklıysa, ihtiyacınız olan kancayı bulun! (kuruluş modu kancalarla dolu )

(add-hook 'before-save-hook #'endless/update-includes)

(defun endless/update-includes (&rest ignore)
  "Update the line numbers of all #+INCLUDE:s in current buffer.
Only looks at INCLUDEs that already have a line number listed!
This function does nothing if not in org-mode, so you can safely
add it to `before-save-hook'."
  (interactive)
  (when (derived-mode-p 'org-mode)
    (save-excursion
      (goto-char (point-min))
      (while (search-forward-regexp
              "^\\s-*#\\+INCLUDE: *\"\\([^\"]+\\)\".*:lines *\"\\([-0-9]+\\)\""
              nil 'noerror)
        (let* ((file (expand-file-name (match-string-no-properties 1)))
               (lines (endless/decide-line-range file)))
          (when lines
            (replace-match lines :fixedcase :literal nil 2)))))))

Normal İfadeler

Bu, dahil edilecek ilk ve son satır olarak kullanılacak normal ifadeleri tanımladığınız yerdir. Her dosya uzantısı için normal ifadelerin bir listesini verebilirsiniz.

(defcustom endless/extension-regexp-map 
  '(("sv" ("^class\\b" . "^endclass\\b") ("^enum\\b" . "^endenum\\b")))
  "Alist of regexps to use for each file extension.
Each item should be
    (EXTENSION (REGEXP-BEGIN . REGEXP-END) (REGEXP-BEGIN . REGEXP-END))
See `endless/decide-line-range' for more information."
  :type '(repeat (cons string (repeat (cons regexp regexp)))))

Arka plan çalışanı

Bu işin çoğunu yapan adam.

(defun endless/decide-line-range (file)
  "Visit FILE and decide which lines to include.
The FILE's extension is used to get a list of cons cells from
`endless/extension-regexp-map'. Each cons cell is a pair of
regexps, which determine the beginning and end of region to be
included. The first one which matches is used."
  (let ((regexps (cdr-safe (assoc (file-name-extension file)
                                  endless/extension-regexp-map)))
        it l r)
    (when regexps
      (save-match-data
        (with-temp-buffer
          (insert-file file)
          (while regexps
            (goto-char (point-min))
            (setq it (pop regexps))
            (when (search-forward-regexp (car it) nil 'noerror)
              (setq l (line-number-at-pos (match-beginning 0)))
              (when (search-forward-regexp (cdr it) nil 'noerror)
                (setq regexps nil
                      r (line-number-at-pos (match-end 0))))))
          (when r (format "%s-%s" l (+ r 1))))))))

1
Eğer önerebilirsem, iki işlevi edebug ve sonra ilkini Mx ile çağır. Bu çok bilgilendirici olmalı. :-)
Malabarba

İşlev tek başına iyi çalışır. Ancak kancanın çağırdığı işleve bir argüman iletmesi gerekir. Dokümanlar için org-export-before-processing-hook, Every function in this hook will be called with one argument: the back-end currently used, as a symbol. Herhangi bir argüman aktarmadığımız için hatayı alıyoruz run-hook-with-args: Wrong number of arguments. Şimdi hangi argümana ekleneceğinden emin değilim endless/update-includes... (&optional dummy)?
Kaushal Modi

@kaushalmodi ayy, benim hatam. Cevabı güncelledim. Yazdığınız şeyi de kullanabilirsiniz.
Malabarba

Tamam .. ekleme (&optional dummy)gerçekten işe yaradı! Ancak işlevi kanca ile çağırmanın ilginç bir yan etkisi. Ben işlevini kullanarak ararsanız M-x, değiştirdiği .orggüncelleştirilmiş satır numaraları ile dosya. Ben sadece html ihracat ve kanca fonksiyonu çağırmak için izin verirseniz, güncellenen satır numaraları dosya değil, sadece ihraç dosyaya yansıtılır .org.
Kaushal Modi

@kaushalmodi Evet, kuruluş kancaları böyle çalışır. Bunun yerine kaydetmeden önce kancaya ekleyebilirsiniz.
Malabarba
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.