[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] org-src--contents-for-write-back : preserve original major-mode,

From: Brent Goodrick
Subject: Re: [O] org-src--contents-for-write-back : preserve original major-mode, and avoid mixing tabs and spaces in org-mode buffers
Date: Fri, 28 Apr 2017 08:29:03 -0700

On Thu, Apr 27, 2017 at 4:04 PM, Nicolas Goaziou <address@hidden> wrote:
> Hello,
> Brent Goodrick <address@hidden> writes:
> > In the current implementation of org-src--contents-for-write-back, the
> > `with-temp-buffer` uses fundamental-mode.
> Correct.
> > Later, while inside that temp buffer, spaces are inserted in to indent
> > the entire source block over to where it needs to be (in my original
> > post, notice that I have the source block within a list item so the
> > source block needs to be aligned properly under that list item, no
> > matter to what depth that list item is).
> Correct.
> > It is in mode hook functions that certain changes to indentation can
> > occur, so that is why I'm switching into that mode.
> This is where I don't follow you. At this point, indentation changes are
> tailored for the source, i.e., Org, buffer. Special indentation rules
> from the source block mode do not apply here.

I do not understand what is meant by "tailored for the source" which
is the Org buffer. All of the indentation changes being made here are
within the temporary buffer created by with-temp-buffer, which is
using fundamental-mode which is not the same as either emacs-lisp-mode
or org-mode. That is the wrong mode to be in when running `indent-line-to`
function since it is that particular editing mode that the user has
control over the `indent-tabs-mode` variable (typically from mode hook
functions). So I conclude that the temporary buffer, at that point in
execution, has to be in the mode of the language used when indenting.

> > But that is not enough: In order for the text to be aligned properly
> > inside the org mode buffer after indentation, there cannot be a mix of
> > tabs and spaces, as shown in my original post. IIRC, `indent-to' is
> > called within the `write-back' function, and `indent-to' is affected
> > by the `indent-tabs-mode' value, which by default in emacs lisp mode
> > buffers, is t.
> You cannot set `indent-tabs-mode' to nil and discard user's
> configuration. What if I want it to be non-nil in Org buffers?

I agree with that. I now see that what I proposed earlier is a not a
solution for that reason. So I have a further suggested change below.

Also I mistakenly referred to `indent-to` when the function is actually

> Another option is to delete any leading indentation and indent it again
> according to `indent-tabs-mode' value in source buffer.

By "in source buffer", do you mean that after the text is inserted
into the Org mode buffer, the code then reindents it again, while the
current mode in that buffer is org-mode (i.e., no longer inside the
temporary buffer, which is fundamental-mode)? If that is the
interpretation, then how is Org mode to know about the syntax of emacs
lisp code? I think it won't and it will indent the emacs lisp code
without proper handling of parens. In fact I played with that a bit
and it is also not going to work (yields left justified text since
fundamental mode knows nothing the parens in Emacs lisp).

Here is my somewhat improved fix. I'm still switching into the
original language mode inside the temp buffer.

(defun org-src--contents-for-write-back ()
  "Return buffer contents in a format appropriate for write back.
        Assume point is in the corresponding edit buffer."
  (let ((indentation (or org-src--block-indentation 0))
        (preserve-indentation org-src--preserve-indentation)
        (contents (org-with-wide-buffer (buffer-string)))
        (write-back org-src--allow-write-back))
    (let ((orig-major-mode major-mode))
        (insert (org-no-properties contents))
        ;; CHANGE: Switch into the mode of the language that was being edited so
        ;; that `indent-tabs-mode` will be respected:
        (funcall orig-major-mode)
        (goto-char (point-min))
        (when (functionp write-back)
          ;; CHANGE: Hack to allow stepping through through this function in
          ;; edebug: I commented out this line:
          ;;   (funcall write-back)
          ;; and inlined the value of write-back here and reindented for
          ;; readability:
          (when (> org-edit-src-content-indentation 0)
            (while (not (eobp))
              (unless (looking-at "[     ]*$")
                (indent-line-to (+ (org-get-indentation)
        ;; CHANGE: Switch into org-mode so that `indent-tabs-mode` in org mode
        ;; buffers will also be respected:
        (unless (or preserve-indentation (= indentation 0))
          (let ((ind (make-string indentation ?\s)))
            (goto-char (point-min))
            (while (not (eobp))
              (when (looking-at-p "[ \t]*\\S-")
                ;; CHANGE: Replace this:
                ;;   (insert ind)
                ;; with this:
                (indent-line-to (+ (org-get-indentation) indentation)))

I've tested this with org-mode's indent-tabs-mode set to t and nil and
it seems to display correctly.

Hence, I'm now thinking the possible bug here was the "(insert ind)"
in the last change above, in addition to the need to switch modes.



P.S.: Thanks for your help on this!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]