joostkremers / pandoc-mode

An Emacs minor mode for interacting with Pandoc.
https://joostkremers.github.io/pandoc-mode/
178 stars 14 forks source link

Change order of citeproc and filters #104

Open btskinner opened 3 years ago

btskinner commented 3 years ago

Is it possible to change the order in which citeproc is called so that it's after a filter? Specifically, I'm trying to use pandoc-crossref for figures/tables in my document, but it needs to go before the call for citeproc in the call. In the terminal, it would have to be:

$ pandoc paper.md --filter pandoc-crossref --citeproc -o paper.pdf

When I add pandoc-crossref as a filter string (like #54), it's added to the end ofpandoc call after citeproc so it throws an error. There may be an option to set this, but I'm new to pandoc-mode (which is great) and I may have missed it.

joostkremers commented 3 years ago

Unfortunately, pandoc-mode doesn't provide any means of specifying the order of arguments passed to pandoc. What's more, I don't see an easy way to fix that... Perhaps the order of options in the settings file could be used to set the order of options on the command line.

btskinner commented 3 years ago

I tried changing the order in the options file, but that didn't work. I think the line of code that's setting the order is the last line in pandoc--format-all-options:

(delq nil (append (list read write output) cli-options (apply #'append list-options) (apply #'append alist-options)))))

If I follow the code correctly, citeproc is formed in list-options while --filter=pandoc-crossref is formed in alist-options. I guess one could switch the two apply statements, but I couldn't say that that wouldn't break other option / filter pairs. I guess a more robust solution would involve allowing filters to have at least two settings, before or after, which would split them around the regular options.

All that said, the juice may not be worth the squeeze on this.

joostkremers commented 3 years ago

I tried changing the order in the options file, but that didn't work.

No, currently, that doesn't work.

I think the line of code that's setting the order is the last line in pandoc--format-all-options:

Yes. But it's basically operating on the assumption that the order is irrelevant.

If I follow the code correctly, citeproc is formed in list-options while --filter=pandoc-crossref is formed in alist-options. I guess one could switch the two apply statements, but I couldn't say that that wouldn't break other option / filter pairs. I guess a more robust solution would involve allowing filters to have at least two settings, before or after, which would split them around the regular options.

That might not be a bad idea.

All that said, the juice may not be worth the squeeze on this.

Well, the aim of pandoc-mode is to be able to control pandoc from within Emacs, so if pandoc makes the order of options important, pandoc-mode should have a way of specifying the order.

btskinner commented 3 years ago

Well, the aim of pandoc-mode is to be able to control pandoc from within Emacs, so if pandoc makes the order of options important, pandoc-mode should have a way of specifying the order.

I'm not an elisp programmer (and I don't like suggesting features that I can't really help with), but if you are able / interested in making a change, then I think it would make pandoc-mode more flexible.

As pseudocode, would the easiest way be:

  1. Have two Filters in the menu of options (C-c / o r): Filters (pre) and Filters (post)
  2. Sort those two into different alists: alist-pre-options and alist-post-options
  3. Pass them into the last line of pandoc--format-all-options like
(delq nil (append (list read write output) cli-options (apply #'append alist-pre-options) (apply #'append list-options) (apply #'append alist-post-options)))))

I may be wrong about where exactly Filter is formed: in pandoc-mode-utils.el it's

(define-pandoc-list-option   filter  (reader "f" "%-23s") file "Filters" "Filter")

which suggests that it's in list-options. But I think the idea is the same (there could be a list-pre-options earlier in the call).

joostkremers commented 3 years ago

Yup, that's pretty much what it would have to look like. Implementing that isn't too difficult. The problematic part IMHO is to figure out how to present it to the user. Your suggestion seems straightforward and simple, but might make it more confusing for users that don't care about the order.

I should also pay more attention to the order of filters relative to each other. Right now, pandoc-mode doesn't allow the user to control the order, but it probably should.

joostkremers commented 3 years ago

I pushed two commits that should improve things a bit. Now, the order in which a user adds filters is also the order in which they're passed to pandoc, and filters are put on the command line before all other options (with the exception of the input and output formats and the output file. If I understand correctly, that should at least fix your immediate problem. If you need more fine-grained control, please let me know, then I'll have to find a better solution.

btskinner commented 3 years ago

That did the trick. The pandoc call is now:

pandoc --read=markdown --write=latex --output=paper.pdf --filter=pandoc-crossref --citeproc --csl=apa.csl --bibliography=sources.bib

which works for my case. Thanks for a great Emacs mode and your quick help!