Skip to content

Commit

Permalink
hydra-ox.el: Emulate org-mode export dispatch
Browse files Browse the repository at this point in the history
* hydra-ox.el (hydra-ox): New radiogroup.
(hydra-ox-html): New hydra.
(hydra-ox-latex): New hydra.
(hydra-ox-text): New hydra.
(hydra-ox): New hydra that includes the above three hydras.
(org-mode-map): Add test binding.

Re #66.
  • Loading branch information
abo-abo committed Mar 5, 2015
1 parent 8dec3cd commit e342c33
Showing 1 changed file with 118 additions and 0 deletions.
118 changes: 118 additions & 0 deletions hydra-ox.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
;;; hydra-ox.el --- Org mode export widget implemented in Hydra

;; Copyright (C) 2015 Free Software Foundation, Inc.

;; Author: Oleh Krehel

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:
;;
;; This shows how a complex dispatch menu can be built with Hydra.

;;; Code:
(require 'org)

(defhydradio hydra-ox ()
(body-only)
(export-scope [buffer subtree])
(async-export)
(visible-only)
(force-publishing))

(defhydra hydra-ox-html (:color blue)
"ox-html"
("H" (org-html-export-as-html
hydra-ox/async-export
(eq hydra-ox/export-scope 'subtree)
hydra-ox/visible-only
hydra-ox/body-only)
"As HTML buffer")
("h" (org-html-export-to-html
hydra-ox/async-export
(eq hydra-ox/export-scope 'subtree)
hydra-ox/visible-only
hydra-ox/body-only) "As HTML file")
("o" (org-open-file
(org-html-export-to-html
hydra-ox/async-export
(eq hydra-ox/export-scope 'subtree)
hydra-ox/visible-only
hydra-ox/body-only)) "As HTML file and open")
("b" hydra-ox/body "back")
("q" nil "quit"))

(defhydra hydra-ox-latex (:color blue)
"ox-latex"
("L" org-latex-export-as-latex "As LaTeX buffer")
("l" org-latex-export-to-latex "As LaTeX file")
("p" org-latex-export-to-pdf "As PDF file")
("o" (org-open-file (org-latex-export-to-pdf)) "As PDF file and open")
("b" hydra-ox/body "back")
("q" nil "quit"))

(defhydra hydra-ox-text (:color blue)
"ox-text"
("A" (org-ascii-export-as-ascii
nil nil nil nil
'(:ascii-charset ascii))
"As ASCII buffer")

("a" (org-ascii-export-to-ascii
nil nil nil nil
'(:ascii-charset ascii))
"As ASCII file")
("L" (org-ascii-export-as-ascii
nil nil nil nil
'(:ascii-charset latin1))
"As Latin1 buffer")
("l" (org-ascii-export-to-ascii
nil nil nil nil
'(:ascii-charset latin1))
"As Latin1 file")
("U" (org-ascii-export-as-ascii
nil nil nil nil
'(:ascii-charset utf-8))
"As UTF-8 buffer")
("u" (org-ascii-export-to-ascii
nil nil nil nil
'(:ascii-charset utf-8))
"As UTF-8 file")
("b" hydra-ox/body "back")
("q" nil "quit"))

(defhydra hydra-ox ()
"
_C-b_ Body only: % -15`hydra-ox/body-only^^^ _C-v_ Visible only: %`hydra-ox/visible-only
_C-s_ Export scope: % -15`hydra-ox/export-scope _C-f_ Force publishing: %`hydra-ox/force-publishing
_C-a_ Async export: %`hydra-ox/async-export
"
("C-b" (hydra-ox/body-only) nil)
("C-v" (hydra-ox/visible-only) nil)
("C-s" (hydra-ox/export-scope) nil)
("C-f" (hydra-ox/force-publishing) nil)
("C-a" (hydra-ox/async-export) nil)
("h" hydra-ox-html/body "Export to HTML" :exit t)
("l" hydra-ox-latex/body "Export to LaTeX" :exit t)
("t" hydra-ox-text/body "Export to Plain Text" :exit t)
("q" nil "quit"))

(define-key org-mode-map (kbd "C-c C-,") 'hydra-ox/body)

(provide 'hydra-ox)

;;; hydra-ox.el ends here

8 comments on commit e342c33

@kaushalmodi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a brief documentation about hydradio?

I am trying to understand the relationship between

(defhydradio hydra-ox ()
  (body-only)
  (export-scope [buffer subtree])
  (async-export)
  (visible-only)
  (force-publishing))

and

("C-b" (hydra-ox/body-only) nil)
("C-v" (hydra-ox/visible-only) nil)
("C-s" (hydra-ox/export-scope) nil)
("C-f" (hydra-ox/force-publishing) nil)
("C-a" (hydra-ox/async-export) nil)

For example, where is (hydra-ox/body-only) defined?

@abo-abo
Copy link
Owner Author

@abo-abo abo-abo commented on e342c33 Mar 6, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can macroexpand the defhydradio to get:

(progn
  (defvar hydra-ox/body-only nil nil)
  (put (quote hydra-ox/body-only)
       (quote range)
       [nil t])
  (defun hydra-ox/body-only nil (hydra--cycle-radio (quote hydra-ox/body-only)))
  (defvar hydra-ox/export-scope nil [buffer subtree])
  (put (quote hydra-ox/export-scope)
       (quote range)
       [nil t])
  (defun hydra-ox/export-scope nil (hydra--cycle-radio (quote hydra-ox/export-scope)))
  (defvar hydra-ox/async-export nil nil)
  (put (quote hydra-ox/async-export)
       (quote range)
       [nil t])
  (defun hydra-ox/async-export nil (hydra--cycle-radio (quote hydra-ox/async-export)))
  (defvar hydra-ox/visible-only nil nil)
  (put (quote hydra-ox/visible-only)
       (quote range)
       [nil t])
  (defun hydra-ox/visible-only nil (hydra--cycle-radio (quote hydra-ox/visible-only)))
  (defvar hydra-ox/force-publishing nil nil)
  (put (quote hydra-ox/force-publishing)
       (quote range)
       [nil t])
  (defun hydra-ox/force-publishing nil (hydra--cycle-radio (quote hydra-ox/force-publishing)))
  (defvar hydra-ox/names
    (quote (hydra-ox/body-only
            hydra-ox/export-scope
            hydra-ox/async-export
            hydra-ox/visible-only
            hydra-ox/force-publishing))))

It's sort of a namespaceish construct that defines

  • a bunch of parameters with a prefix
  • that can assume only the values from [nil t] or e.g. [buffer subtree] if specified
  • a toggle function that cycles the corresponding parameter
  • a list of parameters under this prefix, so it's possible to reset them all at once with
    (hydra-reset-radios hydra-ox/names)

You don't have to use it if you don't want to, it's just a shortcut for writing these things explicitly.

@abo-abo
Copy link
Owner Author

@abo-abo abo-abo commented on e342c33 Mar 6, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot that I changed the parameters order, it should be:

(defhydradio hydra-ox ()
  (body-only)
  (export-scope "scope" [buffer subtree])
  (async-export)
  (visible-only)
  (force-publishing))

that expands to

(progn (defvar hydra-ox/body-only nil nil)
       (put (quote hydra-ox/body-only)
            (quote range)
            [nil t])
       (defun hydra-ox/body-only nil (hydra--cycle-radio (quote hydra-ox/body-only)))
       (defvar hydra-ox/export-scope (quote buffer)
         "scope")
       (put (quote hydra-ox/export-scope)
            (quote range)
            [buffer subtree])
       (defun hydra-ox/export-scope nil (hydra--cycle-radio (quote hydra-ox/export-scope)))
       (defvar hydra-ox/async-export nil nil)
       (put (quote hydra-ox/async-export)
            (quote range)
            [nil t])
       (defun hydra-ox/async-export nil (hydra--cycle-radio (quote hydra-ox/async-export)))
       (defvar hydra-ox/visible-only nil nil)
       (put (quote hydra-ox/visible-only)
            (quote range)
            [nil t])
       (defun hydra-ox/visible-only nil (hydra--cycle-radio (quote hydra-ox/visible-only)))
       (defvar hydra-ox/force-publishing nil nil)
       (put (quote hydra-ox/force-publishing)
            (quote range)
            [nil t])
       (defun hydra-ox/force-publishing nil (hydra--cycle-radio (quote hydra-ox/force-publishing)))
       (defvar hydra-ox/names
         (quote
          (hydra-ox/body-only
           hydra-ox/export-scope
           hydra-ox/async-export
           hydra-ox/visible-only
           hydra-ox/force-publishing))))

@tarsius
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please do something about these warnings:

hydra-ox.el:121:1:Warning: the following functions are not known to be
    defined: org-html-export-as-html, org-html-export-to-html,
    org-latex-export-as-latex, org-latex-export-to-latex,
    org-latex-export-to-pdf, org-ascii-export-as-ascii,
    org-ascii-export-to-ascii

Not sure whether you can just declare these to be defined and then rely on them being autoloaded, or not.

@abo-abo
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarsius How do you trigger warnings in hydra-ox.el? I can't reproduce them.

@tarsius
Copy link
Contributor

@tarsius tarsius commented on e342c33 Aug 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only reproduce this by removing the org-loaddefs.el file. It's usually a mistake if that file does not exist, and loading org actually causes a warning about that file not being available as you can see below.

$ rm ../org/lisp/org-loaddefs.el
$ emacs -Q --batch -L . -L ../org/lisp -f batch-byte-compile *.el

In end of data:
hydra.el:1268:1:Warning: the following functions are not known to be defined:
    ring-insert, ring-length, ring-remove
WARNING: No org-loaddefs.el file could be found from where org.el is loaded.
You need to run "make" or "make autoloads" from Org lisp directory

In end of data:
hydra-ox.el:121:1:Warning: the following functions are not known to be
    defined: org-html-export-as-html, org-html-export-to-html,
    org-latex-export-as-latex, org-latex-export-to-latex,
    org-latex-export-to-pdf, org-ascii-export-as-ascii,
    org-ascii-export-to-ascii

I occasionally recompile all the packages I have installed in alphabetic order after removing all byte compiled files (to avoid old macro implementations leaking into the newly created byte compiled files).

I think that during byte-compilation we should not depend on a package's autoload file being loaded when the package's "main library" is loaded. While it makes sense that Org does that due to its size, it still is quite unusual.

So you should probably add this to hydra-ox.el:

(declare-function org-html-export-as-html 'ox-html)
(declare-function org-html-export-to-html 'ox-html)
(declare-function org-latex-export-as-latex 'ox-latex)
(declare-function org-latex-export-to-latex 'ox-latex)
(declare-function org-latex-export-to-pdf 'ox-latex)
(declare-function org-ascii-export-as-ascii 'ox-ascii)
(declare-function org-ascii-export-to-ascii 'ox-ascii)

Also note the additional warnings about the ring functions. You should add (require 'ring) to hydra.el.

@abo-abo
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarsius Thanks, I just added the declares you mentioned.

@tarsius
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks to you too!

Please sign in to comment.