7

It is a common practice to write Emacs configuration files using literate-programming style in Org mode.

Unfortunately, while improving readability, this comes with significant programming disadvantages. In particular, since there is no backing .el file, Emacs is only aware of the code in the current source block. This means that except for the currently-edited block, navigation, symbol definition, and flycheck are all unavailable.

#+BEGIN_SRC emacs-lisp
  (defun literate-but-invisible ()
    (interactive)
    (message "I close my eyes..."))
#+END_SRC

#+BEGIN_SRC emacs-lisp
  (defun humans-can-read-but-emacs-cannot ()
    (interactive)
    (literate-but-invisible) ; No navigation! Flycheck reports undefined symbol!
    (message "...so that the room will be empty"))
#+END_SRC

Is there any way to tell Emacs to tangle and use the generated .el file to provide these features in Org mode? Such a feature would improve the maintainability of literate Emacs Lisp code.

Note that while it would be a fantastic feature to see Flycheck working for Org and Emacs Lisp simultaneously in one buffer, I am only asking about how to instrument org-edit buffers (the environment you get when you invoke org-edit-special (usually C-c ')). This should be easier since there is only one active mode for the buffer.

I have opened a feature request on the Flycheck repository here, and there is some relevant research in another issue here. However, I am not yet able to construct a solution.

Matthew Piziak
  • 5,958
  • 3
  • 29
  • 77
  • You can evaluate all elisp src blocks when open this file. add a hook on `find-file-hook` etc to detect whether opening emacs config org file. – stardiviner Oct 13 '18 at 04:04
  • @stardiviner Would you be willing to expand your comment into an answer? As it is I do not have enough context to understand your proposed solution. – Matthew Piziak Oct 13 '18 at 04:35

2 Answers2

2

For navigation and symbol definition see https://github.com/jkitchin/scimax/blob/master/scimax-literate-programming.el

You can generate a TAGS file with M-x scimax-lp-generate-tags.

After this, I can navigate to function definitions with M-. and M-,. You need to refresh the TAGS file with that function as things move around and get added, but maybe that can be done in a save-buffer hook or something. Also note that this gives tags relative to the org-file, not to where the definitions are in the source files.

M-x scimax-lp-signature-doc will get some information about the symbol at point if it is defined in the org-file.

I worked out a conceptual way to get flycheck to work in src-blocks in org-files. The idea is to have a proxy file that has the tangled code in it, in exactly the same character positions (ie you change all the other characters to spaces). Then, let flycheck work on that file. Then, transfer the flycheck overlays from the proxy file to the original file. You setup a hook function to update the proxy file on saving, and then update the overlays. Surprisingly, this works pretty well.

You can see the code at https://github.com/jkitchin/scimax/blob/master/scimax-ob-flycheck.org.

This is what a bad bit of code usually looks like Before scimax-ob-flycheck

After turning on scimax-ob-flycheck-mode it looks like:

After turning on scimax-ob-flycheck-mode

John Kitchin
  • 11,555
  • 1
  • 19
  • 41
  • Note that for something like Flycheck, I think it would be completely acceptable if it were only active when `org-edit` is invoked. In that case there would be only one mode active for the buffer. I've edited my question to add some nuance there. – Matthew Piziak Oct 13 '18 at 19:04
  • I have created a solution for this at https://github.com/jkitchin/scimax/blob/master/scimax-ob-flycheck.org. It does more or less what I outlined above using flycheck on a proxy file. There are probably some issues in it still, but it works for me so far! – John Kitchin Oct 14 '18 at 18:39
  • This is brilliant! However, I have trouble reproducing it. I have launched an `emacs -q`, installed dependencies, and then ran `(org-babel-load-file "scimax-ob-flycheck.org")` followed by `(scimax-ob-flycheck-mode +1)`. I do not see any Flycheck errors when I create broken code as a test. – Matthew Piziak Oct 14 '18 at 20:39
  • You have to save the file, which should create the proxy files, and then run flycheck in them after the file is done being checked then the overlays should get transferred. While the org-file is open, there should be a file created in the same directory with an md5 hash and .el extension, if you look in that, you should see the flycheck overlays there. If not, something else is going on. I haven't tried this with a vanilla emacs/setup, maybe you can post your init for that and I could try it out. – John Kitchin Oct 14 '18 at 21:29
  • Okay, yes. I can see `flycheck` overlays in the `md5-hash.el` file. However I cannot see any overlaps in `scimax-ob-flycheck.org` (with `scimax-ob-flycheck-mode` on), nor when using `org-edit-special`. – Matthew Piziak Oct 15 '18 at 18:48
  • I can reproduce this with a vanilla emacs. I guess I have some special mods that work for me. I have pushed some fixes to it that also work in a vanilla emacs for me. – John Kitchin Oct 15 '18 at 22:24
  • As you say yourself this is a partial answer, so I will leave this question unanswered for now. However your research efforts here are fantastic, and very helpful, so I'm awarding you the question bounty. – Matthew Piziak Oct 19 '18 at 18:46
  • Thanks for the bounty. I think it is pretty complete, at least it does everything you indicated: navigation, flycheck, and docstring/args from the org-buffer in the src-blocks. – John Kitchin Oct 19 '18 at 20:12
-2
 (defun org-literate-programming-eval-src-blocks ()
   "Auto evaluate Org buffer all source blocks to get a complete
 project environment when Literate Programming."
   (if (string= (buffer-name) "init.org")
       (org-babel-execute-buffer)))

 (add-hook 'find-file-hook #'org-literate-programming-eval-src-blocks :before)

The upper code add a function to evaluate all source blocks in buffer which matches your file "init.org". The filename can be modified as you needed.

stardiviner
  • 1,888
  • 26
  • 45
  • I'm afraid this does not do anything except evaluate the blocks and add `RESULTS` blocks. Flycheck remains unusable. – Matthew Piziak Oct 13 '18 at 13:24
  • flycheck seems to work fine for me in org-edit mode for emacs-lisp. What does it not do for you? – John Kitchin Oct 13 '18 at 19:36
  • @MatthewPiziak If all your source blocks are emacs-lisp blocks, and evaluated, then all your elisp code should be available for Emacs, flycheck will be aware of that. And also, flycheck works fine on my org-edit-src-block too. – stardiviner Oct 14 '18 at 00:52
  • @JohnKitchin @stardiviner I get `emacs-lisp predicate:nil` `flycheck-verify-setup` due to the fact that `buffer-file-name` is `nil` in the `Org Src` buffers. – Matthew Piziak Oct 14 '18 at 22:16
  • Can set `buffer-file-name` to a temporary fake file. But if want to disable flycheck I think disable that is a good solution. – stardiviner Oct 15 '18 at 01:47