jupyter-org-insert-src-block: Find the closest language to use

If `point' is not on a source block, look near `point' for a source block with
a Jupyter language and use that one.

Closes #66.
This commit is contained in:
Nathaniel Nicandro 2019-03-24 00:11:56 -05:00
parent fbdbe60c95
commit 2c005cab7b
No known key found for this signature in database
GPG key ID: C34814B309DD06B8
2 changed files with 98 additions and 10 deletions

View file

@ -32,6 +32,7 @@
(declare-function org-babel-jupyter-initiate-session "ob-jupyter" (&optional session params)) (declare-function org-babel-jupyter-initiate-session "ob-jupyter" (&optional session params))
(declare-function org-babel-jupyter-src-block-session "ob-jupyter" ()) (declare-function org-babel-jupyter-src-block-session "ob-jupyter" ())
(declare-function org-babel-jupyter-language-p "ob-jupyter" (lang))
(declare-function org-in-src-block-p "org" (&optional inside)) (declare-function org-in-src-block-p "org" (&optional inside))
(declare-function org-narrow-to-subtree "org" ()) (declare-function org-narrow-to-subtree "org" ())
(declare-function org-element-context "org-element" (&optional element)) (declare-function org-element-context "org-element" (&optional element))
@ -49,13 +50,70 @@ beginning of a source block in a list."
:group 'ob-jupyter :group 'ob-jupyter
:type 'integer) :type 'integer)
;;;###autoload (defun jupyter-org-closest-jupyter-language (&optional query)
(defun jupyter-org-insert-src-block (&optional below) "Return the language of the closest Jupyter source block.
"Insert a src block above the current point. If QUERY is non-nil, ask for a language to use instead. Asking
With prefix arg BELOW, insert it below the current point. for which language to use is also done if no Jupyter source
blocks could be found in the buffer.
If point is in a block, copy the header to the new block" Distance is line based, not character based. Also, `point' is
(interactive "P") assumed to not be inside a source block."
(save-excursion
(or (and (null query)
(cl-loop
with start = (line-number-at-pos)
with previous = (ignore-errors
(save-excursion
(org-babel-previous-src-block)
(point)))
with next = (ignore-errors
(save-excursion
(org-babel-next-src-block)
(point)))
with maybe-return-lang =
(lambda ()
(let ((info (org-babel-get-src-block-info 'light)))
(when (org-babel-jupyter-language-p (nth 0 info))
(cl-return (nth 0 info)))))
while (or previous next) do
(cond
((or
;; Maybe return the previous Jupyter source block's language
;; if it is closer to the start point than the next source
;; block
(and previous next (< (- start (line-number-at-pos previous))
(- (line-number-at-pos next) start)))
;; or when there is no next source block
(and (null next) previous))
(goto-char previous)
(funcall maybe-return-lang)
(setq previous (ignore-errors
(org-babel-previous-src-block)
(point))))
(next
(goto-char next)
(funcall maybe-return-lang)
(setq next (ignore-errors
(org-babel-next-src-block)
(point)))))))
;; If all else fails, query for the language to use
(let* ((kernelspec (jupyter-completing-read-kernelspec))
(lang (plist-get (cddr kernelspec) :language)))
(if (org-babel-jupyter-language-p lang) lang
(format "jupyter-%s" lang))))))
;;;###autoload
(defun jupyter-org-insert-src-block (&optional below query)
"Insert a src-block above `point'.
With prefix arg BELOW, insert it below `point'.
If `point' is in a src-block use the language of the src-block and
copy the header to the new block.
If QUERY is non-nil and `point' is not in a src-block, ask for
the language to use for the new block. Otherwise try to select a
language based on the src-block's near `point'."
(interactive (list current-prefix-arg nil))
(if (org-in-src-block-p) (if (org-in-src-block-p)
(let* ((src (org-element-context)) (let* ((src (org-element-context))
(start (org-element-property :begin src)) (start (org-element-property :begin src))
@ -87,8 +145,7 @@ If point is in a block, copy the header to the new block"
:post-blank 1))) :post-blank 1)))
(forward-line -3))) (forward-line -3)))
;; not in a src block, insert a new block, query for jupyter kernel ;; not in a src block, insert a new block, query for jupyter kernel
(let* ((kernelspec (jupyter-completing-read-kernelspec)) (let* ((lang (jupyter-org-closest-jupyter-language query))
(lang (format "jupyter-%s" (plist-get (cddr kernelspec) :language)))
(src-block (jupyter-org-src-block lang "" "\n")) (src-block (jupyter-org-src-block lang "" "\n"))
(blank-after-p (> (save-excursion (blank-after-p (> (save-excursion
(skip-chars-forward "\n")) (skip-chars-forward "\n"))
@ -523,8 +580,8 @@ _S-M-<return>_: Restart/buffer ^ ^ _s_: split
("o" (jupyter-org-clone-block t)) ("o" (jupyter-org-clone-block t))
("m" jupyter-org-merge-blocks) ("m" jupyter-org-merge-blocks)
("s" jupyter-org-split-src-block) ("s" jupyter-org-split-src-block)
("+" jupyter-org-insert-src-block) ("+" (jupyter-org-insert-src-block nil current-prefix-arg))
("=" (jupyter-org-insert-src-block t)) ("=" (jupyter-org-insert-src-block t current-prefix-arg))
("l" org-babel-remove-result) ("l" org-babel-remove-result)
("L" jupyter-org-clear-all-results) ("L" jupyter-org-clear-all-results)
("h" jupyter-org-edit-header) ("h" jupyter-org-edit-header)

View file

@ -1712,6 +1712,37 @@ ABCDEF
(remove-text-properties (point-min) (point-max) '(face)) (remove-text-properties (point-min) (point-max) '(face))
(funcall test-fun 24 '(19 20 21 22 23 26 27 28 29))))) (funcall test-fun 24 '(19 20 21 22 23 26 27 28 29)))))
(ert-deftest jupyter-org-closest-jupyter-language ()
:tags '(org)
(jupyter-org-test
(insert "\
#+BEGIN_SRC jupyter-foo
#+END_SRC
x
#+BEGIN_SRC jupyter-bar
#+END_SRC
#+BEGIN_SRC baz
#+END_SRC
")
(re-search-backward "x")
(should (equal (jupyter-org-closest-jupyter-language)
"jupyter-bar"))
(forward-line -1)
(should (equal (jupyter-org-closest-jupyter-language)
"jupyter-foo"))
(forward-line 2)
(should (equal (jupyter-org-closest-jupyter-language)
"jupyter-bar"))
(goto-char (point-max))
(should (equal (jupyter-org-closest-jupyter-language)
"jupyter-bar"))
(forward-line -3)
(should (equal (jupyter-org-closest-jupyter-language)
"jupyter-bar"))))
(ert-deftest org-babel-jupyter-src-block-session () (ert-deftest org-babel-jupyter-src-block-session ()
:tags '(org) :tags '(org)
(jupyter-org-test (jupyter-org-test