emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Brent Goodrick <bgoodr@gmail.com>
To: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Cc: emacs-orgmode@gnu.org
Subject: Re: 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	[thread overview]
Message-ID: <CAJj=8EHMJwo4N+BkcpZaqB8xqtco_b759CNzt3NBsw8bBc6UdQ@mail.gmail.com> (raw)
In-Reply-To: <87h919zc40.fsf@nicolasgoaziou.fr>

On Thu, Apr 27, 2017 at 4:04 PM, Nicolas Goaziou <mail@nicolasgoaziou.fr> wrote:
>
> Hello,
>
> Brent Goodrick <bgoodr@gmail.com> 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
`indent-line-to`.

> 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))
      (with-temp-buffer
        (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)
org-edit-src-content-indentation)))
              (forward-line))))
        ;; CHANGE: Switch into org-mode so that `indent-tabs-mode` in org mode
        ;; buffers will also be respected:
        (org-mode)
        (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)))
              (forward-line))))
        (buffer-string)))))

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.

WDYT?

Thanks,
Brent

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

  reply	other threads:[~2017-04-28 15:29 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-03  4:15 org-src--contents-for-write-back : preserve original major-mode, and avoid mixing tabs and spaces in org-mode buffers Brent Goodrick
2017-04-22  8:41 ` Nicolas Goaziou
2017-04-23  3:21   ` Brent Goodrick
2017-04-27 23:04     ` Nicolas Goaziou
2017-04-28 15:29       ` Brent Goodrick [this message]
2017-04-29  9:59         ` Nicolas Goaziou
2017-04-29 16:41           ` Brent Goodrick

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAJj=8EHMJwo4N+BkcpZaqB8xqtco_b759CNzt3NBsw8bBc6UdQ@mail.gmail.com' \
    --to=bgoodr@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=mail@nicolasgoaziou.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).