From mboxrd@z Thu Jan 1 00:00:00 1970 From: Brent Goodrick 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 Message-ID: References: <877f2cvnpe.fsf@nicolasgoaziou.fr> <87h919zc40.fsf@nicolasgoaziou.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:60843) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d47pT-0007u3-8L for emacs-orgmode@gnu.org; Fri, 28 Apr 2017 11:29:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d47pS-0006yo-2Q for emacs-orgmode@gnu.org; Fri, 28 Apr 2017 11:29:07 -0400 Received: from mail-io0-x233.google.com ([2607:f8b0:4001:c06::233]:35772) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1d47pR-0006yR-So for emacs-orgmode@gnu.org; Fri, 28 Apr 2017 11:29:05 -0400 Received: by mail-io0-x233.google.com with SMTP id r16so67338046ioi.2 for ; Fri, 28 Apr 2017 08:29:05 -0700 (PDT) In-Reply-To: <87h919zc40.fsf@nicolasgoaziou.fr> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: Nicolas Goaziou Cc: emacs-orgmode@gnu.org On Thu, Apr 27, 2017 at 4:04 PM, Nicolas Goaziou wrote: > > Hello, > > Brent Goodrick 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!