From 433b374c10eab08f3bd244463d0b95cdb3c22f93 Mon Sep 17 00:00:00 2001 From: Eric Schulte Date: Sun, 11 Jul 2010 21:35:58 -0700 Subject: [PATCH] babel: enhanced code block movement functions Thanks to Austin Frank for suggesting these features and to Jonathan Arkell for an implementation suggestion This commit - adds `org-babel-goto-named-result' for jumping to named results - adds TAB-completion to `org-babel-goto-named-src-block' - standardizes on "-src-" instead of "-source-" in all babel functions - adds `org-babel-[next/previous]-src-block' functions and keybindings - documents the above in orgcard.tex * doc/orgcard.tex: update documentation of babel keybindings * lisp/ob-exp.el (org-exp-res/src-name-cleanup): standardized on "-src-" instead of "-source-" * lisp/ob-keys.el (org-babel-key-bindings): updating keybindings for new movement functions * lisp/ob-lob.el (org-babel-lob-ingest): standardized on "-src-" instead of "-source-" * lisp/ob-ref.el (org-babel-ref-resolve-reference): standardized on "-src-" instead of "-source-" * lisp/ob-tangle.el (org-babel-tangle-collect-blocks): standardized on "-src-" instead of "-source-" * lisp/ob.el (org-babel-src-name-regexp): standardized on "-src-" instead of "-source-" (org-babel-src-name-w-name-regexp): adding regexp for matching source names along with their names (org-babel-get-src-block-info): using new named source block regexp (org-babel-result-regexp): adding optional whitespace after result regexp (org-babel-result-w-name-regexp): adding regexp for matching results which have names (org-babel-named-src-block-regexp-for-name): standardized on "-src-" instead of "-source-" (org-babel-map-src-blocks): standardized on "-src-" instead of "-source-" (org-babel-where-is-src-block-head): standardized on "-src-" instead of "-source-" (org-babel-goto-named-src-block): standardized on "-src-" instead of "-source-", also added completing read (org-babel-src-block-names): collects source block names from a file or the current buffer (org-babel-goto-named-result): function for jumping to a named result (org-babel-result-names): returns results names from a file or the current buffer (org-babel-next-src-block): jump to the next source block (org-babel-previous-src-block): jump to the previous source block --- doc/orgcard.tex | 5 ++- lisp/ob-exp.el | 2 +- lisp/ob-keys.el | 14 +++++--- lisp/ob-lob.el | 2 +- lisp/ob-ref.el | 2 +- lisp/ob-tangle.el | 2 +- lisp/ob.el | 81 +++++++++++++++++++++++++++++++++++++++++------ 7 files changed, 89 insertions(+), 19 deletions(-) diff --git a/doc/orgcard.tex b/doc/orgcard.tex index 26e04fb80..dd3c012b3 100644 --- a/doc/orgcard.tex +++ b/doc/orgcard.tex @@ -477,8 +477,11 @@ formula, \kbd{:=} a field formula. \key{execute code block at point}{C-c C-c} \key{open results of code block at point}{C-c C-o} -\key{preview body of code block at point}{C-c C-v p} +\key{view expanded body of code block at point}{C-c C-v v} \key{go to named code block}{C-c C-v g} +\key{go to named result}{C-c C-v r} +\key{go to the next code block}{C-c C-v n} +\key{go to the previous code block}{C-c C-v p} \key{execute all code blocks in current buffer}{C-c C-v b} \key{execute all code blocks in current subtree}{C-c C-v s} \key{tangle code blocks in current file}{C-c C-v t} diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el index 0b6819ce0..a715abb5c 100644 --- a/lisp/ob-exp.el +++ b/lisp/ob-exp.el @@ -138,7 +138,7 @@ processing has taken place." (goto-char (point-min)) (while (org-re-search-forward-unprotected (concat - "\\("org-babel-source-name-regexp"\\|"org-babel-result-regexp"\\)") + "\\("org-babel-src-name-regexp"\\|"org-babel-result-regexp"\\)") nil t) (delete-region (progn (beginning-of-line) (point)) diff --git a/lisp/ob-keys.el b/lisp/ob-keys.el index 2cc523a21..0121c759b 100644 --- a/lisp/ob-keys.el +++ b/lisp/ob-keys.el @@ -51,13 +51,19 @@ functions.") (describe-bindings org-babel-key-prefix)) (defvar org-babel-key-bindings - '(("e" . org-babel-execute-src-block) + '(("p" . org-babel-previous-src-block) + ("\C-p" . org-babel-previous-src-block) + ("n" . org-babel-next-src-block) + ("\C-n" . org-babel-next-src-block) + ("e" . org-babel-execute-src-block) ("\C-e" . org-babel-execute-src-block) ("o" . org-babel-open-src-block-result) ("\C-o" . org-babel-open-src-block-result) - ("\C-p" . org-babel-expand-src-block) - ("p" . org-babel-expand-src-block) - ("g" . org-babel-goto-named-source-block) + ("\C-v" . org-babel-expand-src-block) + ("v" . org-babel-expand-src-block) + ("g" . org-babel-goto-named-src-block) + ("r" . org-babel-goto-named-result) + ("\C-r" . org-babel-goto-named-result) ("\C-b" . org-babel-execute-buffer) ("b" . org-babel-execute-buffer) ("\C-s" . org-babel-execute-subtree) diff --git a/lisp/ob-lob.el b/lisp/ob-lob.el index cc7596c2a..9f0245166 100644 --- a/lisp/ob-lob.el +++ b/lisp/ob-lob.el @@ -46,7 +46,7 @@ add files to this list use the `org-babel-lob-ingest' command." (defun org-babel-lob-ingest (&optional file) "Add all source-blocks defined in FILE to `org-babel-library-of-babel'." (interactive "f") - (org-babel-map-source-blocks file + (org-babel-map-src-blocks file (let* ((info (org-babel-get-src-block-info)) (source-name (intern (nth 4 info)))) (when source-name diff --git a/lisp/ob-ref.el b/lisp/ob-ref.el index 14679bbd2..a7f5af91d 100644 --- a/lisp/ob-ref.el +++ b/lisp/ob-ref.el @@ -134,7 +134,7 @@ return nil." (goto-char (point-min)) (if (let ((result_regexp (concat "^[ \t]*#\\+\\(TBLNAME\\|RESNAME\\|RESULTS\\):[ \t]*" (regexp-quote ref) "[ \t]*$")) - (regexp (concat org-babel-source-name-regexp + (regexp (concat org-babel-src-name-regexp (regexp-quote ref) "\\(\(.*\)\\)?" "[ \t]*$"))) ;; goto ref in the current buffer (or (and (not args) diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index 7d140dbdb..36cb34917 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -200,7 +200,7 @@ the form used by `org-babel-spec-to-string' grouped by language. Optional argument LANG can be used to limit the collected source code blocks by language." (let ((block-counter 0) blocks) - (org-babel-map-source-blocks (buffer-file-name) + (org-babel-map-src-blocks (buffer-file-name) (setq block-counter (+ 1 block-counter)) (let* ((link (progn (call-interactively 'org-store-link) (org-babel-clean-text-properties diff --git a/lisp/ob.el b/lisp/ob.el index 160cdf9b7..7b7be3dc8 100644 --- a/lisp/ob.el +++ b/lisp/ob.el @@ -38,6 +38,7 @@ (declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) (declare-function tramp-file-name-user "tramp" (vec)) (declare-function tramp-file-name-host "tramp" (vec)) +(declare-function org-icompleting-read "org" (&rest args)) (declare-function org-edit-src-code "org" (context code edit-buffer-name)) (declare-function org-open-at-point "org" (&optional in-emacs reference-buffer)) (declare-function org-save-outline-visibility "org" (use-markers &rest body)) @@ -94,10 +95,15 @@ the C-c C-c key binding." :group 'org-babel :type 'boolean) -(defvar org-babel-source-name-regexp +(defvar org-babel-src-name-regexp "^[ \t]*#\\+\\(srcname\\|source\\|function\\):[ \t]*" "Regular expression used to match a source name line.") +(defvar org-babel-src-name-w-name-regexp + (concat org-babel-src-name-regexp + "\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)") + "Regular expression matching source name lines with a name.") + (defvar org-babel-src-block-regexp (concat ;; (1) indentation (2) lang @@ -137,9 +143,7 @@ added to the header-arguments-alist." (setq indent (car (last info))) (setq info (butlast info)) (forward-line -1) - (if (looking-at - (concat org-babel-source-name-regexp - "\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)")) + (if (looking-at org-babel-src-name-w-name-regexp) (progn (setq info (append info (list (org-babel-clean-text-properties (match-string 2))))) @@ -253,11 +257,15 @@ header arguments as well.") (make-variable-buffer-local 'org-babel-current-buffer-properties) (defvar org-babel-result-regexp - "^[ \t]*#\\+res\\(ults\\|name\\)\\(\\[\\([[:alnum:]]+\\)\\]\\)?\\:" + "^[ \t]*#\\+res\\(ults\\|name\\)\\(\\[\\([[:alnum:]]+\\)\\]\\)?\\:[ \t]*" "Regular expression used to match result lines. If the results are associated with a hash key then the hash will be saved in the second match data.") +(defvar org-babel-result-w-name-regexp + (concat org-babel-result-regexp + "\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)")) + (defvar org-babel-min-lines-for-block-output 10 "If number of lines of output is equal to or exceeds this value, the output is placed in a #+begin_example...#+end_example @@ -277,7 +285,7 @@ can not be resolved.") "Hook for functions to be called after `org-babel-execute-src-block'") (defun org-babel-named-src-block-regexp-for-name (name) "This generates a regexp used to match a src block named NAME." - (concat org-babel-source-name-regexp (regexp-quote name) "[ \t\n]*" + (concat org-babel-src-name-regexp (regexp-quote name) "[ \t\n]*" (substring org-babel-src-block-regexp 1))) ;;; functions @@ -625,7 +633,7 @@ portions of results lines." (lambda () (org-add-hook 'change-major-mode-hook 'org-babel-show-result-all 'append 'local))) -(defmacro org-babel-map-source-blocks (file &rest body) +(defmacro org-babel-map-src-blocks (file &rest body) "Evaluate BODY forms on each source-block in FILE." (declare (indent 1)) `(let ((visited-p (get-file-buffer (expand-file-name ,file))) @@ -857,7 +865,7 @@ If the point is not on a source block then return nil." (or (save-excursion ;; on a source name line (beginning-of-line 1) - (and (looking-at org-babel-source-name-regexp) (forward-line 1) + (and (looking-at org-babel-src-name-regexp) (forward-line 1) (looking-at org-babel-src-block-regexp) (point))) (save-excursion ;; on a #+begin_src line @@ -874,9 +882,12 @@ If the point is not on a source block then return nil." (point)))))) ;;;###autoload -(defun org-babel-goto-named-source-block (&optional name) +(defun org-babel-goto-named-src-block (name) "Go to a named source-code block." - (interactive "ssource-block name: ") + (interactive + (let ((completion-ignore-case t)) + (list (org-icompleting-read "source-block name: " + (org-babel-src-block-names) nil t)))) (let ((point (org-babel-find-named-block name))) (if point ;; taken from `org-open-at-point' @@ -896,6 +907,29 @@ org-babel-named-src-block-regexp." (re-search-backward regexp nil t)) (match-beginning 0))))) +(defun org-babel-src-block-names (&optional file) + "Returns the names of source blocks in FILE or the current buffer." + (save-excursion + (when file (find-file file)) (goto-char (point-min)) + (let (names) + (while (re-search-forward org-babel-src-name-w-name-regexp nil t) + (setq names (cons (org-babel-clean-text-properties (match-string 2)) + names))) + names))) + +;;;###autoload +(defun org-babel-goto-named-result (name) + "Go to a named result." + (interactive + (let ((completion-ignore-case t)) + (list (org-icompleting-read "source-block name: " + (org-babel-result-names) nil t)))) + (let ((point (org-babel-find-named-result name))) + (if point + ;; taken from `org-open-at-point' + (progn (goto-char point) (org-show-context)) + (message "result '%s' not found in this buffer" name)))) + (defun org-babel-find-named-result (name) "Return the location of the result named NAME in the current buffer or nil if no such result exists." @@ -906,6 +940,33 @@ buffer or nil if no such result exists." "[ \t]" (regexp-quote name) "[ \t\n\f\v\r]") nil t) (beginning-of-line 0) (point)))) +(defun org-babel-result-names (&optional file) + "Returns the names of results in FILE or the current buffer." + (save-excursion + (when file (find-file file)) (goto-char (point-min)) + (let (names) + (while (re-search-forward org-babel-result-w-name-regexp nil t) + (setq names (cons (org-babel-clean-text-properties (match-string 4)) + names))) + names))) + +;;;###autoload +(defun org-babel-next-src-block (&optional arg) + "Jump to the next source block. +With optional prefix argument ARG, jump forward ARG many source blocks." + (interactive "P") + (when (looking-at org-babel-src-block-regexp) (forward-char 1)) + (re-search-forward org-babel-src-block-regexp nil nil (or arg 1)) + (goto-char (match-beginning 0)) (org-show-context)) + +;;;###autoload +(defun org-babel-previous-src-block (&optional arg) + "Jump to the previous source block. +With optional prefix argument ARG, jump backward ARG many source blocks." + (interactive "P") + (re-search-backward org-babel-src-block-regexp nil nil (or arg 1)) + (goto-char (match-beginning 0)) (org-show-context)) + (defvar org-babel-lob-one-liner-regexp) (defun org-babel-where-is-src-block-result (&optional insert info hash indent) "Return the point at the beginning of the result of the current