org-func.el (2021B)
1 ;;; org-func.el --- -*- lexical-binding: t -*- 2 ;; 3 4 ;; https://endlessparentheses.com/updating-org-mode-include-statements-on-the-fly.html 5 ;;;###autoload 6 (defun save-and-update-includes () 7 "Update the line numbers of #+INCLUDE:s in current buffer. 8 Only looks at INCLUDEs that have either :range-begin or :range-end. 9 This function does nothing if not in `org-mode', so you can safely 10 add it to `before-save-hook'." 11 (interactive) 12 (when (derived-mode-p 'org-mode) 13 (save-excursion 14 (goto-char (point-min)) 15 (while (search-forward-regexp 16 "^\\s-*#\\+INCLUDE: *\"\\([^\"]+\\)\".*:range-\\(begin\\|end\\)" 17 nil 'noerror) 18 (let* ((file (expand-file-name (match-string-no-properties 1))) 19 lines begin end) 20 (forward-line 0) 21 (when (looking-at "^.*:range-begin *\"\\([^\"]+\\)\"") 22 (setq begin (match-string-no-properties 1))) 23 (when (looking-at "^.*:range-end *\"\\([^\"]+\\)\"") 24 (setq end (match-string-no-properties 1))) 25 (setq lines (decide-line-range file begin end)) 26 (when lines 27 (if (looking-at ".*:lines *\"\\([-0-9]+\\)\"") 28 (replace-match lines :fixedcase :literal nil 1) 29 (goto-char (line-end-position)) 30 (insert " :lines \"" lines "\"")))))))) 31 32 (defun decide-line-range (file begin end) 33 "Visit FILE and decide which lines to include. 34 BEGIN and END are regexps which define the line range to use." 35 (let (l r) 36 (save-match-data 37 (with-temp-buffer 38 (insert-file-contents file) 39 (goto-char (point-min)) 40 (if (null begin) 41 (setq l "") 42 (search-forward-regexp begin) 43 (setq l (line-number-at-pos (match-beginning 0)))) 44 (if (null end) 45 (setq r "") 46 (search-forward-regexp end) 47 (setq r (1+ (line-number-at-pos (match-end 0))))) 48 (format "%s-%s" (+ l 1) (- r 1)))))) ;; Exclude wrapper 49 50 (provide 'org-func) 51 ;;; org-func.el ends here