From: Seth Burleigh <wburle4@gmail.com>
To: Eric Schulte <schulte.eric@gmail.com>
Cc: emacs-orgmode@gnu.org, "Štěpán Němec" <stepnem@gmail.com>
Subject: Re: Re: [babel] Painless integration of source blocks with language
Date: Sun, 9 Jan 2011 18:59:25 -0600 [thread overview]
Message-ID: <AANLkTi=L8u03UQ_RiVrAX=Qh=5Mv_cf2wUKmX6UhbTn=@mail.gmail.com> (raw)
In-Reply-To: <8739p2ot4q.fsf@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 786 bytes --]
As an update, ive been working on something i call chunks.
Basically, they are blocks of code (i.e. emacs overlays) that are linked
together.
So far, i have each ns of my clojure code in one source block which is
then tangled to one file.
So, i would like to open the tangled file and then make changes, and finally
'push' those changes to the org file.
Theres some bugs (pushing when mark is next to a parantheses), but i think
it is going in the correct way to also include noweb tangling. In the
attached code, you hit f8 in a source block to link the block to its file
and then f8 if you want to unlink it, and you hit ctrl-alt-p to push changes
from source file to org file.
just execute lp.el in an ielm buffer. and try it out with the previous test
org file that was attached.
[-- Attachment #1.2: Type: text/html, Size: 890 bytes --]
[-- Attachment #2: lp.el --]
[-- Type: application/octet-stream, Size: 8796 bytes --]
(require 'cl)
;;UTILS
(defun inform (operation arg)
(if arg
(progn (message "%s success!" operation) arg)
(info "%s failed!" operation)))
(defun char (i str)
"get char at index"
(substring str i (+ i 1)))
;;cant get multiline regex to work for some reason. grr
(defun string-trim-right (test-str)
"trim all right hand whitespace,newlines"
(let ((place (- (length test-str) 1)) (continue t))
(while continue
(let ((c (char place test-str)))
(if (or (equalp c "\n")
(equalp c "\r")
(equalp c " "))
(decf place)
(progn (setq continue nil) (incf place)))
(if (= place 0) (setq continue nil))))
(substring test-str 0 place)))
(defmacro with-file (file &rest body)
"open up file in a buffer, and set current buffer to it"
`(with-current-buffer (find-file-noselect ,file t) ,@body))
(defun info (&rest args)
"message which returns nil"
(apply #'message args)
nil)
(defmacro comment (&rest body) nil)
(defun mkdir (file)
"given file name, make a directory if needed"
(let ((dir (file-name-directory file-name)))
(if dir (make-directory dir t))))
;;;
(defun ob-expand (&optional arg info params)
"Expand the current source code block.
Expand according to the source code block's header
arguments and pop open the results in a preview buffer.
Trims whitespaces at the very right of text"
(interactive)
(let* ((info (or info (org-babel-get-src-block-info)))
(lang (nth 0 info))
(params (setf (nth 2 info)
(sort (org-babel-merge-params (nth 2 info) params)
(lambda (el1 el2) (string< (symbol-name (car el1))
(symbol-name (car el2)))))))
(body (setf (nth 1 info)
(if (and (cdr (assoc :noweb params))
(string= "yes" (cdr (assoc :noweb params))))
(org-babel-expand-noweb-references info) (nth 1 info))))
(cmd (intern (concat "org-babel-expand-body:" lang)))
(expanded (funcall (if (fboundp cmd) cmd 'org-babel-expand-body:generic)
body params)))
(string-trim-right expanded)))
;;TODO: more efficient
(defun ob-name ()
(nth 4 (ob-info)))
(defun ob-info ()
"return info, making sure to trim right hand whitespaces. The reason to trim is so that , in the indirect macro, we can search for the beginning and end
of the chunk. i was getting some problems with newlines at the very end messing things up - so i trimmed them away. im sure theres a better way."
(let ((info (org-babel-get-src-block-info)))
(if info `(,(first info) ,(string-trim-right (second info)) ,@(cddr info)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun tangle-chunk (tag)
"find code block with the tag: if found, tangle it to file"
(let* ((chunk (find-chunk tag))
(file-name (first chunk)))
(when chunk
(if (file-exists-p file-name)
(delete-file file-name))
(mkdir file-name)
(with-temp-buffer
(insert (second chunk))
;; We avoid append-to-file as it does not work with tramp.
(let ((content (buffer-string)))
(with-temp-buffer
(goto-char (point-max))
(insert content)
(write-region nil nil file-name))))
chunk)))
(defun find-chunk (tag)
"find the src block with the appropriate tag (i.e. srcname)"
(when tag
(flet ((chunk!
(tag prev)
(save-excursion
(goto-char (point-min))
(let (chunks)
(if (re-search-forward (format "<<[ \t]*%s[ \t]*>>" tag) nil t)
(let ((info (ob-info)))
(if (member info prev)
(message "when finding chunk, infinite loop detected")
(if (and (equalp (first info) "clojure")
info (not (equalp "no"
(cdr (assoc :tangle (third info))))))
(list (cdr (assoc :tangle (third info)))
(ob-expand (second info))
(point))
(chunk! (ob-name) (append prev (list info)))))))))))
(let ((info (ob-info)))
(if (not (equalp "no" (cdr (assoc :tangle (third info)))))
(list (cdr (assoc :tangle (third info)))
(ob-expand (second info))
(point))
(chunk! tag nil))))))
;;TODO: if youre at end of buffer and the chunk is at the end of the buffer, the chunk will grow - how to inserta new line?
;;TODO: cursor is set to beginning of chunk in synced buffer. fix?
(defmacro comment (&rest body))
(defun set-color (chunk color)
(overlay-put chunk 'face (list :background color)))
(defvar lp-default-color "gray94")
(defun* new-chunk (start end buffer &optional (color lp-default-color))
(interactive)
(let ((chunk (make-overlay start end buffer t t)))
(set-color chunk (if color color lp-default-color))
;;(overlay-put chunk 'modification-hooks '(mod-hook))
chunk))
(defun link (from to)
(pushnew to (overlay-get from 'lp-link)))
(defun bi-link (node1 node2)
(link node1 node2)
(link node2 node1))
(defun chunks (o) (overlay-get o 'lp-link))
(defun overlay-string (overlay)
(save-excursion
(set-buffer (overlay-buffer overlay))
(buffer-substring-no-properties
(overlay-start overlay)
(overlay-end overlay))))
;;TODO: instead of replacing entire region, replace only part that has changed
;;TODO: remove orphoned chunks?
(defun chunk? (chunk) (and (overlayp chunk) (overlay-buffer chunk)))
(defun push-string (str to &optional length)
(when (chunk? to)
(let ((start (overlay-start to))
(end (overlay-end to)))
(save-excursion
(set-buffer (overlay-buffer to))
(delete-region start end)
(goto-char start)
(insert str)
(move-overlay to start (+ start (length str)))))))
(defun push-chunk (from to &optional length)
(push-string (overlay-string from) to))
(defun delete-chunks (c)
(if (listp c)
(mapcar #'delete-chunk c)
(when (chunk? c) (delete-overlay c))))
;;after modification hook
(defun mod-hook (from type start end &optional length)
(when type
(dolist (to (chunks from))
(push-chunk from to))))
(defun get-chunk ()
(first (overlays-in (point-min) (point-max))))
(defun get-chunks ()
(overlays-in (point-min) (point-max)))
;;src block chunks
(defun new-src-block-chunk (&optional color)
(save-excursion
(when (org-babel-mark-block)
(new-chunk (point) (mark) (current-buffer)))))
(defun get-src-block-chunk ()
(save-excursion
(when (org-babel-mark-block)
(first (overlays-in (point) (mark))))))
(defun get-src-block-chunk-create (&optional color)
(let ((chunk (get-src-block-chunk)))
(if chunk chunk (new-src-block-chunk color))))
(defun delete-src-block-chunk ()
(delete-chunks (get-src-block-chunk)))
;;file chunks
(defun new-src-block-file-chunk (&optional color)
"get tangled file associated with chunk, open it, and create a chunk out of the whole file"
(let ((file-name (first (find-chunk (ob-name)))))
(if file-name
(with-file
file-name
(save-excursion
(new-chunk (point-min) (point-max) (current-buffer) color)))
(info "couldn't do it"))))
(defun get-src-block-file-chunk ()
(let ((file-name (first (find-chunk (ob-name)))))
(when file-name
(with-file
file-name
(get-chunk)))))
(defun get-src-block-file-chunk-create (&optional color)
(let ((chunk (get-src-block-file-chunk)))
(if chunk chunk (new-src-block-file-chunk color))))
(defun delete-src-block-file-chunk ()
(delete-chunks (get-src-block-file-chunk)))
;;linking
(defun unlink-src-block ()
(interactive)
(delete-src-block-file-chunk)
(delete-src-block-chunk))
(defun pull-src-block ()
(interactive)
(let ((chunk (get-src-block-chunk))
(file-chunk (get-src-block-file-chunk)))
(if (and chunk file-chunk)
(inform "pull" (push-chunk file-chunk chunk))
(info "only found chunk %s and file-chunk %s" chunk file-chunk))))
(defun bi-link-src-block (&optional color)
(interactive)
(let ((chunk (get-src-block-chunk-create)))
(if chunk
(let ((file-chunk (get-src-block-file-chunk-create (or color "white"))))
(if file-chunk
(bi-link chunk file-chunk)
(progn (info "couldn't chunkify file") (unlink-src-block))))
(info "couldn't chunkify src block"))))
(defun linked? ()
(get-src-block-chunk))
(defun push-src-block ()
(interactive)
(let ((source (first (chunks (get-chunk)))))
(if source
(inform "push"
(push-string
(buffer-substring-no-properties (point-min) (point-max))
source))
(message "chunks are only %s" source))))
;;TODO; for some reason, when f8 is by a paren, dont work
(define-key org-mode-map (kbd "<f8>")
(lambda ()
(interactive)
(if (linked?)
(unlink-src-block)
(bi-link-src-block))))
;;TODO: minor mode
(global-set-key
(kbd "M-P")
(lambda ()
(interactive)
(if (linked?) (pull-src-block) (push-src-block))))
[-- Attachment #3: Type: text/plain, Size: 201 bytes --]
_______________________________________________
Emacs-orgmode mailing list
Please use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode
next prev parent reply other threads:[~2011-01-10 0:59 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-08 22:29 [babel] Painless integration of source blocks with language Seth Burleigh
2011-01-09 1:54 ` Eric Schulte
2011-01-09 9:40 ` Štěpán Němec
2011-01-09 17:59 ` Eric Schulte
2011-01-10 0:59 ` Seth Burleigh [this message]
2011-01-10 2:13 ` Eric Schulte
2011-01-10 3:49 ` Seth Burleigh
2011-01-10 4:01 ` Seth Burleigh
2011-01-11 17:00 ` Eric Schulte
2011-01-10 18:46 ` Eric S Fraga
2011-01-11 17:12 ` Eric Schulte
[not found] ` <AANLkTi=dNTn6HBeR4wV7039FDDyPGtmWbmL0biFwT-ta@mail.gmail.com>
2011-01-11 23:09 ` Seth Burleigh
2011-01-13 9:11 ` Eric S Fraga
2011-01-13 15:23 ` Seth Burleigh
2011-01-13 21:23 ` Eric Schulte
2011-01-13 23:44 ` Seth Burleigh
2011-01-16 15:31 ` Eric Schulte
2011-01-17 9:29 ` Sébastien Vauban
2011-01-17 16:18 ` Eric Schulte
2011-01-17 19:32 ` Sébastien Vauban
2011-01-17 22:15 ` Seth Burleigh
2011-01-17 22:44 ` Sébastien Vauban
2011-01-18 18:11 ` Seth Burleigh
2011-01-18 18:14 ` Seth Burleigh
2011-01-18 18:38 ` Seth Burleigh
2011-01-19 7:28 ` Eric Schulte
2011-01-24 14:49 ` Seth Burleigh
2011-01-18 19:53 ` Bastien
2011-01-24 11:56 ` Dan Davison
2011-01-24 18:56 ` Eric S Fraga
2011-01-26 10:43 ` Sébastien Vauban
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='AANLkTi=L8u03UQ_RiVrAX=Qh=5Mv_cf2wUKmX6UhbTn=@mail.gmail.com' \
--to=wburle4@gmail.com \
--cc=emacs-orgmode@gnu.org \
--cc=schulte.eric@gmail.com \
--cc=stepnem@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).