reddit / emacs

Program to execute entire org-mode files

ShadowRylander · 2022-02-25 08:25
Hello! Would there happen to be any utilities to execute entire org-mode files, similar to [bashup's](https://github.com/bashup) [mdsh](https://github.com/bashup/mdsh)? This allows users to execute markdown files via bash. I'd like to combine it with a `nix-shell` shebang! Thank you kindly for the help!
Kaligule · 2022-02-25 08:39
You could do different things here. The easiest way is probably to call emacs from the command line and tell it to execute a certain function to tangle and execute the file (I think `org-babel-execute-buffer`). Alternatively you could first tangle and then execute via an interpreter of your choice (depending on what code it is, bash probably). Your command could look like this: ``` emacs my-org-file.org --quick --batch --load=my-custom-tangle-program.el --kill ```
[deleted] · 2022-02-25 08:41
You could write a script that calls emacs from the shell with the -e command. You would need to pass in some emacs lisp that would call org babel tangle and then pass that new file to whatever you use the execute the code. ​ It should be pretty easy to hack up with elisp.
ShadowRylander · 2022-02-25 09:00
I guess I could use the former in a [script](https://gist.github.com/ctarbide/99b0ac9f7d6bef19cdd3e9f71b4cbcf7), then use the script as the shebang interpreter; I'm assuming I'd have to create a temporary buffer and insert the contents of the file received from the interpreter call into it before using the function?
ShadowRylander · 2022-02-25 09:02
Another user suggested `org-babel-execute-buffer`; I'm thinking of using [this](https://gist.github.com/ctarbide/99b0ac9f7d6bef19cdd3e9f71b4cbcf7) to create a script to use as the shebang interpreter, inserting the file contents from the interpreter into a temporary buffer, then executing the buffer using the aforementioned function.
Kaligule · 2022-02-25 09:03
That could be a way to do it, yes.
[deleted] · 2022-02-25 09:04
That sounds like a better way to go. I was unaware of that command as I've never used it. Best of luck to you! You should be able to make it work.
ShadowRylander · 2022-02-25 09:14
I most certainly hope so! 😸 I'll post the script soon as I make sure it's working!
ShadowRylander · 2022-02-25 09:15
I'll give it a whirl, then post the script when I get it working! Thanks for all the help!
_viz_ · 2022-02-25 09:51
https://emacsconf.org/2021/talks/exec
ShadowRylander · 2022-02-25 10:43
I went through the documentation but coudn't figure out how to actually run the example they gave [here](https://github.com/tgbugs/orgstrap#hello-orgstrap)... 😅
[deleted] · 2022-02-25 10:45
[deleted]
ShadowRylander · 2022-02-25 10:45
Would you happen to know of a way to print to console / stdout? I have this currently: Interpreter: ```sh #!/usr/bin/env sh ":"; exec emacs --quick --script "$0" -- "$@" # -*- mode: emacs-lisp; lexical-binding: t; -*- (require 'ob-core) (setq org-confirm-babel-evaluate nil) (with-temp-buffer (pop argv) (apply 'insert argv) (org-babel-execute-buffer)) ``` Test file: ``` #!/home/shadowrylander/testing #+begin_src emacs-lisp (princ (format-time-string "%Y%m%d%H%M%S%N")) (terpri) ;; or this? (append-to-file "here I come to save the day\n" nil "/dev/stdout") #+end_src ```
ShadowRylander · 2022-02-25 10:45
Would you happen to know of a way to print to console / stdout? I have this currently: Interpreter: ```sh #!/usr/bin/env sh ":"; exec emacs --quick --script "$0" -- "$@" # -*- mode: emacs-lisp; lexical-binding: t; -*- (require 'ob-core) (setq org-confirm-babel-evaluate nil) (with-temp-buffer (pop argv) (apply 'insert argv) (org-babel-execute-buffer)) ``` Test file: ``` #!/home/shadowrylander/testing #+begin_src emacs-lisp (princ (format-time-string "%Y%m%d%H%M%S%N")) (terpri) ;; or this? (append-to-file "here I come to save the day\n" nil "/dev/stdout") #+end_src ```
ftrx · 2022-02-25 15:31
IMVHO: do not try to integrate Emacs in *nix environment, do the opposite. Emacs is not designed to be unix software, it's not designed to be integrated, it's a whole environment alone, where the OS is just a complex bootloader since LispM are no more. Emacs is designed as a unique standalone software, multics alike, where anything is accessible, changeable at runtime, under user control, that's it's strength. Unix on contrary is designed as a poor man solution not really flexible not complete but enough simple to run on low cost hw. It's evolution prove the Unix idea was wrong: thanks to it's cheapness get spread but quickly reach it's own evolutionary limits and start to violate it's own paradigm (think about GUI environment, completely alien in unix terms, lacking IPCs, KISSness etc. The actual results it a hybrid system that work better than anything else widespread simply because anything widespread is actually crap. The less crappy one win. But ANYTHING in IT these days converge to classic desktop ideas, sometimes without even knowing the past. From the UIs to the integration paradigm.
ShadowRylander · 2022-02-25 19:30
Well, yes; but I'm kind of trying to do exactly that: make a polyglot executable. 😅
ShadowRylander · 2022-02-25 20:18
Ah, no; never mind. Found it. I'd like to stay away from emacs for very quick scripts, though; as far as I can tell, I'd have to be in emacs for this to work.
Ideabile · 2022-02-25 21:18
To output to stdout you probably want to set the property `:results` to `silent output`. `silent` makes sure the execution is logged in the buffer *Messages* which is usually bind to stdout. https://orgmode.org/manual/Results-of-Evaluation.html
Ideabile · 2022-02-25 21:19
I was gonna propose the same talk.
Ideabile · 2022-02-25 21:25
The trick there is to make a shebang that runs emacs and does `org-babel-buffer-execute` of the same file. Has some nifty tricks implement in it. Look at https://github.com/tgbugs/orgstrap/blob/master/README.org
ShadowRylander · 2022-02-26 03:20
I was actually misunderstanding how a shebang interpreter works; after I put the contents of the file in the temporary buffer instead, it started working. However, `:results silent output` actually helped me with another problem I was having: I wanted to get rid of the `executing Emacs-Lisp code block...` messages and similar, so I inhibited message output, and used `princ` for printing to stdout instead. Then I tried it with another language, but it wasn't working, despite its `org-babel-execute` function being set up similar to `emacs-lisp`. Now, though, wih `:results silent output`, it does indeed get output to messages, but I'm still getting the `executing Emacs-Lisp code block...` messages as well. Do I have to advise the functions creating those messages, or is there another way for me to get rid of them?
ShadowRylander · 2022-02-26 05:55
Actually, I just advised the message function to not run for those specific messages.
ftrx · 2022-02-26 07:42
It's the contrary :-) A "polyglot executable" means something that integrate itself in another environment, not an environment that integrate anything, if you see Emacs as an OS anything should be in Emacs, not Emacs inside something else, in some other UI (CLI, in your case), or environments (posix, windows, ...). Emacs as an OS means that you boot to Emacs and everything is inside Emacs, there is no external CLI, no external WM, no external tools. Actually that's not possible since LispM are long gone, of course, but at least Emacs can be used inside it as an operating environment, it's also a WM (EXWM), try to use it outside is like full-stack virtualization on x86: a big load of overhead for very poor results. In that case use the tools of the environment you are in (unix tools, shell, IPCs) works far better, because as the anything-in-Emacs while less integrated are still a somewhat integrated environment... Unix environment is poor compare to Emacs: you need to write a mix o C and script to use it really, and C is not actually much user friendly, however unix shell scripts with unix tools + IPCs are a bit integrated, it's pretty easy to combine tools with pipes, a poor kind of functions and their return values, and it's the sole strength of unix things built on top of it, to overcame it's limit, are just not unix but workarounds of a bad design that pile up one after another without being really able to solve the basic design flaw, using Emacs as one of them is the worst tool on top, it's slow, not designed for that, so you completely loss the sole good part of the unix model, just working with poor workarounds...
ShadowRylander · 2022-02-26 08:16
I'm actually switching to EXWM; I'm quite excited to be using all sorts of keymap setups with it! However, in this case, what I really wanted was to simply use an org-file as a slightly more integrated literate program; otherwise, I'd be forced to either tangle my files, which I'm doing for most of my config already, or the mdsh tool above, for use with markdown. This is just for a small bootstrap program.
ftrx · 2022-02-26 11:52
It's perfectly legit, only it will not IMO/IME works as you hope/wish... For mere tangle-ing you can set "tangle on file save" so when you change and save your org-file it get auto-tangle-ed, just put at the bottom of the file # Local variables: # eval: (add-hook 'after-save-hook (lambda () (org-babel-tangle)) t t) # end: If you also want/instead want exporting for instance to html # Local variables: # eval: (add-hook 'after-save-hook (lambda () (org-html-export-to-html t)) t t) # end: You can hide such extras with a dedicated :noexport: heading as needed, at the first run you can mark that file safe to avoid being asked if you want to auto-run code from it. Another possible option is craft a function to do what you want and call it not via Emacs but via Emacs daemon, so you do not have the full Emacs bootup process before the run, Emacs daemon outside EXWM can be run at login either via a homegrown script that auto-start it in your WM/DE or via systemd as an user service. The benefit is that Emacs start with your session so "appear" to work in a snap, the downside is that if you freeze Emacs you have to restart the daemon.
ShadowRylander · 2022-02-26 20:09
Hmm; I think I'll put those two in my emacs config itself, for org-mode and its child major modes...
ftrx · 2022-02-27 09:12
:-) of course since they are just eval you can put there any sexp, for install run make in shell to build a LaTeX block on .tex file save, also you can write `elisp:` org-mode clickable links if needed, for instance: [[elisp:(progn (org-babel-goto-named-src-block "name-of-src-block") (org-babel-execute-src-block-maybe))][click to run name-of-src-block]] or anything else, essentially you can inject code almost everywhere and more or less easily execute or auto execute it, that's the power of integration of the system itself and of the concept of code and data together; the main explanation of this reasoning IMVHO can be stated as "if my computer system can solve an ode and send mail why I can't solve an ode while writing a mail?" cut&paste common in *nix GUI are poor man manual pipe, inside Emacs you do not need them in most cases :-)