kaushalmodi / ox-hugo

A carefully crafted Org exporter back-end for Hugo
https://ox-hugo.scripter.co
GNU General Public License v3.0
867 stars 130 forks source link

(setq require-final-newline 'ask) asks all the time. It would be nice if it didn't. #671

Closed matta closed 1 year ago

matta commented 1 year ago

Update I've rewritten this issue based on new understanding.

How Emacs treats require-final-newline

The default value for Emacs' require-final-newline is nil, but most programming and text modes set require-final-newline to t based on the value of mode-require-final-newline.

This can be confirmed by setting require-final-newline to nil and then loading up a buffer in text-mode, or markdown-mode, org-mode or any programming mode. The buffer-local value becomes t.

So, the behavior is that in most text and programming modes Emacs appends a final newline automatically, without prompting the user, regardless of their require-final-newline setting. This suggests that most users will leave require-final-newline alone, since Emacs just does the right thing in "text and programming" buffers.

Emacs handles (setq require-final-newline 'ask) in a specific and documented way. From the docstring:

Any other non-nil value means ask user whether to add a newline, when saving.

In my case, I also have this set to ask and exporting from ox-hugo causes a prompt about adding the final newline.

How Org handles require-final-newline

It seems that most org exporters ensure they append the newline themselves, without leaning on file.el and the user's require-final-newline setting. I know this because I have (setq require-final-newline 'ask) and I use other exporters without being prompted or seeing exported files without newlines.

This is not the first time this issues has happened with org export. Here is a similar patch for the same issue sent against org-latex export, but the code has changed a lot since then:

How ox-hugo handles require-final-newline

For Markdown generated by ox-hugo the generated buffer appears to use the user's global require-final-newline value. This is strange because the same user can edit Markdown files and will get require-final-newline set to t by way of mode-require-final-newline, since Markdown inherits from either text mode or a prog mode.

Note that there is some weird stuff happening during a call to org-hugo-export-to-md with respect to this variable. See my next comment: https://github.com/kaushalmodi/ox-hugo/issues/671#issuecomment-1253006047.

Actual Behavior

First:

(setq require-final-newline 'ask)

Then export with ox-hugo. It prompts to add the final newline to the .md file.

Then:

(setq require-final-newline nil)

Then export with ox-hugo. It will generate Markdown without a final newline.

Finally:

(setq require-final-newline t)

Then export with ox-hugo. It will generate Markdown with a final newline.

I have not observed this with other org export formats (html, text). They seem to unconditionally append a final newline without prompting.

Expected Behavior

The "Actual Behavior" above is Emacs behaving as it should given a buffer that isn't in a text or programming mode. I suspect that ox-hugo generates Markdown in perhaps fundamental mode, and this is the root of the problem.

Ideally, ox-hugo would change to generate Markdown files "as if" they were edited in Markdown mode. This would include always behaving as if require-final-newline was t, as it is in text and programming modes.

This would bring ox-hugo behavior in line with most text and programming modes, and most user expectations.

I don't think this issue is best resolved by asking the user to set require-final-newline to t. That option there to control Emacs behavior when it encounters an arbitrary file of unknown format (i.e. not a file known to be text, markup, source code, etc). It is the job of specific modes to decide if mode-require-final-newline is most appropriate instead. Here ox-hugo, or perhaps org mode itself, should play the role of these modes and generate output that is most sensible to the format generated -- i.e. always with a final newline for Markdown content. It should allow the user to leave require-final-newline to something they want for all other "don't know the file format" situations.

How to Reproduce the Issue

See Actual Behavior

Example Org File

n/a (I think any will do)

Generated Markdown File or Error

n/a (I think any will do)

Ox-Hugo Debug Information

Debug information for ox-hugo

Emacs Version

GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.34, cairo version 1.16.0)
 of 2022-08-10 (commit e7b348b08ac5cea01141ece6b06f95c6d0b8c292)

Org Version

Org mode version 9.5.4 (release_9.5.4-17-g6e991f @ /home/matt/git/emacs-build/lisp/org/)

Hugo Version

=hugo= binary not found in PATH

Org load-path shadows

No Org mode shadows found in load-path

Debug Info
org-hugo-section "posts"
org-hugo-use-code-for-kbd nil
org-hugo-preserve-filling t
org-hugo-delete-trailing-ws t
org-hugo-prefer-hyphen-in-tags t
org-hugo-allow-spaces-in-tags t
org-hugo-tag-processing-functions (org-hugo–tag-processing-fn-replace-with-spaces-maybe org-hugo–tag-processing-fn-replace-with-hyphens-maybe)
org-hugo-auto-set-lastmod nil
org-hugo-export-with-toc nil
org-hugo-export-with-section-numbers nil
org-hugo-front-matter-format "toml"
org-hugo-default-static-subdirectory-for-externals "ox-hugo"
org-hugo-external-file-extensions-allowed-for-copying ("jpg" "jpeg" "tiff" "png" "svg" "gif" "mp4" "pdf" "odt" "doc" "ppt" "xls" "docx" "pptx" "xlsx")
org-hugo-date-format "%Y-%m-%dT%T%z"
org-hugo-paired-shortcodes ""
org-hugo-suppress-lastmod-period 0.0
org-hugo-front-matter-format "toml"
matta commented 1 year ago

Something odd is happening with respect to require-final-newline. I set up this advice to set require-final-newline nil when exporting. The point is to suppress the prompt. Something happens while executing org-hugo-export-to-md that causes require-final-newline to become its global value after the export operation occurs.

(defun my-set-require-final-newline (func &rest args)
  (let ((require-final-newline nil))
    (message "BEGIN with require-final-newline set to %s" require-final-newline)
    (apply func args)
    (message "END with require-final-newline set to %s" require-final-newline)))

(advice-add #'org-hugo-export-to-md
            :around
            #'my-set-require-final-newline)

I see this in *Messages*:

BEGIN with require-final-newline set to nil
Buffer about.md does not end in newline.  Add one? (y or n) y
Wrote /home/matt/git/hugo-quickstart/content/about.md
END with require-final-newline set to ask
matta commented 1 year ago

...and when I (setq require-final-newline nil) globally the prompt stops happening, but the generated .md file does not have a final newline.

So we're back to issue #666.

matta commented 1 year ago

I sent a patch to fix this in ox-hugo itself, but for those who can't wait the advice I set up in the :config forms below hacks ox-hugo to fix the issue too (and will remain harmless even after the fix lands in an ox-hugo version you are using).

(use-package ox-hugo
  :ensure t   ; Auto-install the package from Melpa
  :pin melpa  ; `package-archives' should already have ("melpa" . "https://melpa.org/packages/")
  :after ox
  :config
  (defun my-ox-hugo-ensure-newline (str)
    "Return STR with a newline appended if there is not one already."
    (if (string-suffix-p "\n" str)
        str
      (concat str "\n")))
  (advice-add #'org-hugo-inner-template
              :filter-return
              #'my-ox-hugo-ensure-newline))
kaushalmodi commented 1 year ago

Thanks for your contribution. I am on vacation and will be able to take a look at this after October second week.

kaushalmodi commented 1 year ago

This issue should be now fixed as I merged your https://github.com/kaushalmodi/ox-hugo/pull/672 PR manually in https://github.com/kaushalmodi/ox-hugo/commit/8fbd301c03296253bfb5ee193770e1da3ea2df1a.

The main change from your PR was to not entirely remove org-trim from org-hugo-inner-template, but to alteast trim leading blank lines using string-trim-left.

org-blackfriday-inner-template is not used by ox-hugo, so I left it unchanged.

kaushalmodi commented 1 year ago

Closing this issue as there was no response.