Here is some code to do almost (but not quite) everything you want. The following two functions are to be added to your init file:
(defun my-org-babel-make-func (name)
"Construct a string defining the function, then parse the
string into a Lisp s-expression and eval that to actually
define the function."
(let ((s (format "(defun my-org-babel-%s () (interactive) (org-sbe \"%s\"))"
name name)))
(eval (read s))))
(defun my-org-babel-function-maker(filename)
"Map the form over all the code blocks in the file. The form
gets the name of the block and if non-nil, calls the make-func function
to define the function for that name."
(org-babel-map-src-blocks filename
(let ((name (plist-get (cadr (org-element-at-point)) :name)))
(when name
(my-org-babel-make-func name))))
nil)
I hope the comments are enough to convey what the functions are doing.
Then if you have an Org mode file foo.org
with named code blocks like this:
* foo
#+name: hello
#+begin_src emacs-lisp
"Hello"
#+end_src
#+name: good-bye
#+begin_src emacs-lisp
"Good Bye"
#+end_src
you can execute (my-org-babel-function-maker "foo.org")
and then you should have commands my-org-babel-hello
and my-org-babel-good-bye
that you can execute with M-x my-org-babel-hello
or M-x my-org-babel-good-bye
.
If you want this to be done when you open the file you can use a file local variables block to execute the function maker when the file is opened:
... named code blocks as above ...
* COMMENT Local variables
# Local variables:
# eval: (my-org-babel-function-maker (buffer-file-name))
# End:
Caveats:
- no error checking
- blocks with duplicate names are not handled the way you want:
org-sbe
will execute the named code block - if there is more than one code block with that name, it will run whichever one it wants: which one that is depends on the implementation of org-sbe
and is outside the scope of this answer. I would suggest you avoid blocks with the same name in the file.
- it would be nice if these functions were defined locally for this file
only, but that's not the way it works: functions are global in scope in Emacs Lisp, so
my-org-babel-hello
will exist everywhere. If you execute it in a different file that has a code block named hello
, it will happily run that code block; and if there is no such code block, it will complain.