Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/src lines #187

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 107 additions & 57 deletions org-transclusion-src-lines.el
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
;; Add a new transclusion type
(add-hook 'org-transclusion-add-functions
#'org-transclusion-add-src-lines)
(add-hook 'org-transclusion-add-functions
#'org-transclusion-add-thing-at-point)
;; Keyword values
(add-hook 'org-transclusion-keyword-value-functions
#'org-transclusion-keyword-value-lines)
Expand All @@ -54,8 +56,9 @@

;; Transclusion content formating
(add-hook 'org-transclusion-content-format-functions
#'org-transclusion-content-format-src-lines)

#'org-transclusion-content-format-lines)
(add-hook 'org-transclusion-content-format-functions
#'org-transclusion-content-format-src)
;; Open source buffer
(add-hook 'org-transclusion-open-source-marker-functions
#'org-transclusion-open-source-marker-src-lines)
Expand All @@ -65,40 +68,26 @@

;;; Functions

(defun org-transclusion--bounds-of-n-things-at-point (thing count)
"Return the bounds of COUNT THING (s) -at-point."
(save-excursion
(let ((bounds (bounds-of-thing-at-point thing)))
(when bounds
(push-mark (car bounds) t t)
(goto-char (cdr bounds))
(while (and (> count 1) bounds)
(setq bounds (bounds-of-thing-at-point thing))
(when bounds
(if (> count 1)
(forward-thing thing)
(goto-char (cdr bounds)))
(setq count (1- count))))
(car (region-bounds))))))

(defun org-transclusion-add-src-lines (link plist)
"Return a list for non-Org text and source file.
Determine add function based on LINK and PLIST.

Return nil if PLIST does not contain \":src\" or \":lines\" properties."
(cond
((plist-get plist :src)
(append '(:tc-type "src")
(org-transclusion-content-src-lines link plist)))
;; :lines needs to be the last condition to check because :src INCLUDE :lines
((or (plist-get plist :lines)
(plist-get plist :end)
;; Link contains a search-option ::<string>
;; and NOT for an Org file
(and (org-element-property :search-option link)
(not (org-transclusion-org-file-p (org-element-property :path link)))))
(append '(:tc-type "lines")
(org-transclusion-content-range-of-lines link plist)))))
(let ((type
(cond
((plist-get plist :src)
(setq type "src"))
;; :lines needs to be the last condition to check because :src INCLUDE :lines
((or (plist-get plist :lines)
(plist-get plist :end)
;; Link contains a search-option ::<string>
;; and NOT for an Org file
(and (org-element-property :search-option link)
(not (org-transclusion-org-file-p (org-element-property :path link)))))
(setq type "lines")))))
(when type
(append (list :tc-type type)
(org-transclusion-content-range-of-lines link plist)))))

(defun org-transclusion-content-range-of-lines (link plist)
"Return a list of payload for a range of lines from LINK and PLIST.
Expand Down Expand Up @@ -153,7 +142,7 @@ it means from line 10 to the end of file."
(save-excursion
(goto-char start-pos)
(back-to-indentation)
(org-transclusion--bounds-of-n-things-at-point thing-at-point count)))))
(org-transclusion-bounds-of-n-things-at-point thing-at-point count)))))
(end-pos (cond ((when thing-at-point (cdr bounds)))
((when end-search-op
(save-excursion
Expand Down Expand Up @@ -192,28 +181,24 @@ it means from line 10 to the end of file."
:src-beg beg
:src-end end)))))))

(defun org-transclusion-content-src-lines (link plist)
"Return a list of payload from LINK and PLIST in a src-block.
This function is also able to transclude only a certain range of
lines with using :lines n-m property. Refer to
`org-transclusion-content-range-of-lines' for how the notation
for the range works."
(let* ((payload (org-transclusion-content-range-of-lines link plist))
(src-lang (plist-get plist :src))
(rest (plist-get plist :rest)))
;; Modify :src-content if applicable
(when src-lang
(setq payload
(plist-put payload :src-content
(let ((src-content (plist-get payload :src-content)))
(concat
(format "#+begin_src %s" src-lang)
(when rest (format " %s" rest))
"\n"
(org-transclusion-ensure-newline src-content)
"#+end_src\n")))))
;; Return the payload either modified or unmodified
payload))
(defun org-transclusion-content-format-src (type content plist)
"Format text CONTENT from source before transcluding.
Return content modified (or unmodified, if not applicable)."
(when (plist-member plist :src)
(let ((content (org-transclusion-ensure-newline content))
(src-lang (plist-get plist :src))
(rest (plist-get plist :rest)))
;; Modify :src-content if applicable
(when src-lang
(setq content
(concat
(format "#+begin_src %s" src-lang)
(when rest (format " %s" rest))
"\n"
content
"#+end_src\n")))
;; Return the content either modified or unmodified
content)))

(defun org-transclusion-keyword-value-lines (string)
"It is a utility function used converting a keyword STRING to plist.
Expand Down Expand Up @@ -305,6 +290,31 @@ for non-Org text files including program source files."
(cons src-ov tc-ov))))

;;; Thing-at-point

(defun org-transclusion-bounds-of-n-things-at-point (thing count)
"Return the bounds of COUNT THING (s) -at-point."
(save-excursion
(let ((bounds (bounds-of-thing-at-point thing)))
(when bounds
(push-mark (car bounds) t t)
(goto-char (cdr bounds))
(while (and (> count 1) bounds)
(setq bounds (bounds-of-thing-at-point thing))
(when bounds
(if (> count 1)
(forward-thing thing)
(goto-char (cdr bounds)))
(setq count (1- count))))
(car (region-bounds))))))

(defun org-transclusion-add-thing-at-point (link plist)
"Return a list for non-Org text and source file for a thing-at-point.
Determine add function based on LINK and PLIST."
(when (plist-member plist :thing-at-point)
(let ((type "thing-at-point"))
(append (list :tc-type type)
(org-transclusion-content-thing-at-point link plist)))))

(defun org-transclusion-keyword-value-thing-at-point (string)
"It is a utility function used converting a keyword STRING to plist.
It is meant to be used by `org-transclusion-get-string-to-plist'.
Expand All @@ -314,21 +324,61 @@ match any valid elisp symbol (but please don't quote it)."
(when (string-match ":thing-at-point \\([[:alnum:][:punct:]]+\\)" string)
(list :thing-at-point (org-strip-quotes (match-string 1 string)))))

(defun org-transclusion-content-format-src-lines (type content indent)
(defun org-transclusion-content-format-lines (type content plist)
"Format text CONTENT from source before transcluding.
Return content modified (or unmodified, if not applicable).

This is the default one. It only returns the content as is.

INDENT is the number of current indentation of the #+transclude."
(when (org-transclusion-src-lines-p type)
(when (or (string= type "lines") (string= type "thing-at-point"))
(let ((content (org-transclusion-ensure-newline content)))
(org-transclusion-content-format type content indent))))
(org-transclusion-content-format type content plist))))

(defun org-transclusion-ensure-newline (str)
(if (not (string-suffix-p "\n" str))
(concat str "\n")
str))

(defun org-transclusion-content-thing-at-point (link plist)
"Return a list of payload for a thing-at-point from LINK and PLIST."
(let* ((path (org-element-property :path link))
(search-option (org-element-property :search-option link))
(type (org-element-property :type link))
(entry-pos) (buf)
(thing-at-point (plist-get plist :thing-at-point))
(thing-at-point (when thing-at-point (make-symbol thing-at-point))))
(if (not (string= type "id")) (setq buf (find-file-noselect path))
(let ((filename-pos (org-id-find path)))
(setq buf (find-file-noselect (car filename-pos)))
(setq entry-pos (cdr filename-pos))))
(when buf
(with-current-buffer buf
(org-with-wide-buffer
(let* ((start-pos (cond
(entry-pos)
((when search-option
(save-excursion
(ignore-errors
;; FIXME `org-link-search' does not
;; return postion when eithher
;; ::/regex/ or ::number is used
(if (org-link-search search-option)
(line-beginning-position))))))
((point-min))))
(end-search-op (plist-get plist :end))
(bounds (let ((count (if end-search-op
(string-to-number end-search-op) 1)))
(save-excursion
(goto-char start-pos)
(back-to-indentation)
(org-transclusion-bounds-of-n-things-at-point thing-at-point count))))
(end-pos (cdr bounds))
(content (buffer-substring-no-properties start-pos end-pos)))
(list :src-content content
:src-buf (current-buffer)
:src-beg start-pos
:src-end end-pos)))))))

(provide 'org-transclusion-src-lines)
;;; org-transclusion-src-lines.el ends here
17 changes: 9 additions & 8 deletions org-transclusion.el
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ based on the following arguments:
(insert
(run-hook-with-args-until-success
'org-transclusion-content-format-functions
type content (plist-get keyword-values :current-indentation)))
type content keyword-values))
(setq end (point))
(setq end-mkr (set-marker (make-marker) end))
(unless copy
Expand Down Expand Up @@ -1045,7 +1045,7 @@ This function sssumes the buffer is an Org buffer."
(push (org-element-property :level h) list)))
(when list (seq-min list))))

(defun org-transclusion-content-format-org (type content _indent)
(defun org-transclusion-content-format-org (type content _plist)
"Format text CONTENT from source before transcluding.
Return content modified (or unmodified, if not applicable).

Expand All @@ -1070,18 +1070,19 @@ content."
;; Return the temp-buffer's string
(buffer-string)))))

(defun org-transclusion-content-format (_type content indent)
(defun org-transclusion-content-format (_type content plist)
"Format text CONTENT from source before transcluding.
Return content modified (or unmodified, if not applicable).

This is the default one. It only returns the content as is.

INDENT is the number of current indentation of the #+transclude."
(with-temp-buffer
(insert content)
;; Return the temp-buffer's string
(set-left-margin (point-min)(point-max) indent)
(buffer-string)))
(let ((indent (plist-get plist :current-indentation)))
(with-temp-buffer
(insert content)
;; Return the temp-buffer's string
(set-left-margin (point-min)(point-max) indent)
(buffer-string))))

(defun org-transclusion-content-org-marker (marker plist)
"Return a list of payload from MARKER and PLIST.
Expand Down
2 changes: 1 addition & 1 deletion test/things-at-point-dir/story.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
This is a story

Once upon a time. This paragraph should be transcluded. This is a story.
This is a sentence before. Once upon a time. This paragraph should be transcluded. This is a story.
And if I have a hard line break, I belive this line is still part of
the paragraph as defined by ... thing-at-point I think.

Expand Down