3

In brief:

I would like to programmatically mimic the org mode sequence C-c C-e h o to export a buffer to HTML and open the web browser.

My scenario:

  • I have a written a shell-command (in my code snippet below, this command is remplaced by the simple "more" command) that processes the current buffer file (the (buffer-file-name) part).
  • the shell command (here "more") generates an org mode compatible output and stores it in new_buffer.
  • my problem: I want to export this new_buffer into an html file and open the browser (like the manual C-c C-e h o sequence).
  • then I kill the temporary new_buffer

-> I do not know how to do that. For the moment I use org-html-export-as-html, however this function simply exports the created new_buffer into a new *Org HTML Export* buffer.

What I have done so far (with my brittle emacs-lisp knowledge):

 (defun generate_html()
  (interactive)
  (let ((new_buffer (generate-new-buffer (concat (buffer-file-name) ".org"))))
    (shell-command (concat "more " (buffer-file-name)) new_buffer)
    (org-html-export-as-html ) ;; <-- what to do here to mimic C-c C-e h o ?
    (kill-buffer new_buffer)))
2
  • I was looking for the same scenario solution. Solved by using package org-preview-html and M-x eww-browse-with-external-browser (key binding &) when needed.
    – Y. E.
    Nov 2, 2020 at 13:26
  • @Y.E. thanks for these extra information. Nov 2, 2020 at 13:52

4 Answers 4

2

My org-mode version is 9.4, Emacs version is 25.1.50.1.

I'd do

(org-open-file (org-html-export-to-html))

to programmatically export the org buffer to html and open it in a browser.

I looked for the definition function org-html-export-to-html and looked around in the same file, stopping where the shortcut menu is defined:

(?o "As HTML file and open"
    (lambda (a s v b)
      (if a (org-html-export-to-html t s v b)
    (org-open-file (org-html-export-to-html nil s v b)))))

With trace-function of org-html-export-to-html I saw that its arguments were all nil, and as the whole arglist is optional, it may be omitted.

1
  • BTW, 25.1.50 is a bleeding-edge (i.e. code in-development) from 3-4 years ago. You're strongly encouraged to upgrade to either the current bleeding edge (28.0.50) or to a released version of Emacs.
    – Stefan
    Oct 29, 2020 at 13:30
1

Looks like you'll need to define your own command to do it. If you look in ox-html.el and search for ":menu-entry" (on my machine [Org 9.0.9], it's on line 105), you'll see that C-c C-e h H and C-c C-e h h point to commands in ox-html.el, but C-c C-e h o is implemented via a lambda function that you'll have to reproduce. No idea why it was done differently than the other options.

3
  • Thanks for this information. At worst, maybe I can save the exported html into a file and open it with another shell-command chromium file.hmtl Jan 24, 2019 at 20:10
  • 5
    The anonymous function just handles async export. Since the OP is exporting synchronously, only the else part is needed: (org-open-file (org-html-export-to-html)) -- all the optional arguments are nil.
    – NickD
    Jan 25, 2019 at 2:47
  • @NickD thanks for the comment, I will try that today Jan 25, 2019 at 7:53
1

The solution to my alternative issue (I used pandoc, more below) may apply to your's as well.

I was looking for a CGI-based approach to render org files in the browser, thus implicitly publishing them on the fly. This would allow me to work with the org files without having to actively publish them.

In the past, I took a lot of notes using ReStructured Text and later AsciiDoc. I had implemented a solution for each of the formats, but ended up with this handy Perl-based script that would do the conversion on the fly. AsciiDoc, MarkDown and ReStructured Text are covered, but org gave me a headache as I simply could not render the result of org-html-export-as-html.

When invoking

emacs <source.org> --batch --kill -l ~/.emacs -f org-html-export-to-html

on the terminal, a file source.html is generated, but when I put the command in my CGI:

emacs <source.org> --batch --kill -l ~/.emacs -f org-html-export-to-html && cat source.html

it did not come up. This wasn't anyway what I wanted, as an HTML file would have been generated.

I did not find a way of making Emacs redirect the result of org-html-export-as-html to stdout in batch mode. All in all, the whole thing seemed too complicated, until I looked for an alternative way of converting org to html: https://pandoc.org/.

Now I have a single sgml.pl that will convert all these formats on the fly to HTML and thus can be used as a CGI for viewing them on the browser.

This is circumventing Emacs and should therefore perhaps not belong to this forum. I apologise.

Let me know if you're interested in the code.

Best,

Denis

Ok, since I have been asked (I hope this helps):

The below CGI works for both Apache2 and Nginx.

Just to recap,

In Apache2, a handler is defined:

<IfModule mod_actions.c>`
    Action convert-sgml /cgi/sgml.pl`
    AddHandler convert-sgml .adoc .md .org .rst .txt`
...
</IfModule>

In Nginx:

location ~ \.(adoc|md|org|rst|txt)$ {`
    fastcgi_param PATH_TRANSLATED $document_root$document_uri;`
    rewrite ^(.+\.)(adoc|md|org|rst|txt)$ /cgi-bin/sgml.pl?$document_root$document_uri last;`
...
}

The actual CGI code (pandoc does not convert into AsciiDoc, hence using asciidoctor):

#! /usr/bin/perl

# Obtain the server software from the signature (Apache/nginx),
# in order to determine which environment variable will have
# the name of the file to be converted.
$ENV{'SERVER_SOFTWARE'}=~/^([A-Za-z]+)/;
my $serverName=$&;
my %httpd=(
    'Apache','PATH_TRANSLATED'
    ,'nginx','QUERY_STRING'
    );
my $input=$ENV{$httpd{$serverName}};
my $ext=$input;

# Determine the file type (asciidoc/markdown/org/restructured text)
# and choose the corresponding converter
my %sgml=(
    'asciidoc','\.(adoc|txt)'
    ,'markdown','\.md'
    ,'org','\.org'
    ,'rst','\.rst'
    );
my %processor=(
    'asciidoc',"/opt/local/bin/asciidoctor -a last-update-label! -o - '%s'"
    ,'markdown',"/usr/local/bin/pandoc '%s'"
    ,'org',"/usr/local/bin/pandoc '%s'"
    ,'rst',"/usr/local/bin/pandoc '%s'"
    );
my $cmd;
foreach my $key (keys %sgml) {
    if ($input =~ /$sgml{$key}/) {
    $cmd=sprintf("$processor{$key}",$input);
    last;
    }
}

use CGI ':all';
use utf8;
use open ':encoding(utf8)';
binmode(STDOUT, ":utf8");
print header;
#print "<pre>\ninput=".$input."\noutput=".$output."\next=".$ext."\ncmd=".$cmd."\n</pre>\n";
system("$cmd");
1
  • thanks for the comment. Yes it would be nice to have the code. Too big to post it here? Jan 24, 2020 at 9:26
0

I came to this solution, that do what I wanted:

  • calls a shell command I have written in C++ code_to_org that transforms some source code into an org mode compatible document
  • exports it to a html file and starts the web-browser to visualize it.

.

(defun my-code-to-html()
  (interactive)
  (save-buffer)
  (setq current_buffer (current-buffer))
  (setq current_filename (buffer-file-name))
  (with-temp-buffer
    (shell-command (concat "code_to_org " current_filename) (current-buffer))
    (org-open-file (org-export-to-file 'html (concat current_filename ".html")))
    )
  )
2
  • 3
    Good! --- btw, you might want to look into learning how to use the let form in elisp. setq creates global variables, which can eventually catch up with you. let (and its sister let*) create local variables that disappear when it's done. Cheers! Jan 25, 2019 at 15:08
  • Thank you for your clarification @SueD.Nymme. That is one of my regret, not having learnt (emacs) lisp. I must do that. Jan 25, 2019 at 15:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.