emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: "Sébastien Miquel" <sebastien.miquel@posteo.eu>
To: Ihor Radchenko <yantar92@posteo.net>
Cc: emacs-orgmode@gnu.org
Subject: Re: [BUG] Source block indentation does not work properly for yaml-mode [9.6.6 ( @ /home/user/.emacs.d/elpa/org-9.6.6/)]
Date: Mon,  3 Jul 2023 13:48:11 +0000	[thread overview]
Message-ID: <40b8bf4b-2c1c-ad5b-7109-e0684973bf81@posteo.eu> (raw)
In-Reply-To: <87cz19gn6i.fsf@localhost>

[-- Attachment #1: Type: text/plain, Size: 296 bytes --]


Ihor Radchenko writes:
> For the second scenario, no special treatment of current line is needed.
> For the first scenario, why do we need to do it all the way in
> `org-src--contents-for-write-back'? Why not directly in
> `org-indent-line'?

Ah, yes, that is much better.

-- 
Sébastien Miquel

[-- Attachment #2: 0001-org-src.el-Use-native-value-of-indent-tabs-mode-for-.patch --]
[-- Type: text/x-patch, Size: 13075 bytes --]

From 9d31a71bc0ab7cfd466ecad60037d00c62bdd9f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Miquel?= <sebastien.miquel@posteo.eu>
Date: Tue, 27 Jun 2023 09:23:01 +0200
Subject: [PATCH] org-src.el: Use native value of `indent-tabs-mode' for
 indentation

* lisp/org.el (org-indent-line): Simplify native indentation inside
src block.  Ensure we add the org indentation if the line is empty.
* lisp/org-macs.el (org-do-remove-indentation): Preserve
indentation (spaces vs tabs) past the common indentation to remove.
Do not empty blank lines.
* lisp/org-src.el (org-src--contents-for-write-back): Preserve the
native indentation (spaces vs tabs).  If necessary, add a common org
indentation to the block according to org's `indent-tabs-mode'.
(org-src-font-lock-fontify-block): In case of mixed indentation,
display the tab characters with a fixed width, according to the native
tab width value.
* testing/lisp/test-org-src.el (test-org-src/indented-blocks): Update
tests.  Indentation no longer obeys `indent-tabs-mode' from the org
buffer, but is separated in two parts.
---
 lisp/org-macs.el             |  9 +++--
 lisp/org-src.el              | 52 ++++++++++++++-----------
 lisp/org.el                  | 23 ++++-------
 testing/lisp/test-org-src.el | 75 ++++++++++++++++++++++--------------
 4 files changed, 89 insertions(+), 70 deletions(-)

diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index 51dbfe118..ea210dc60 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -483,9 +483,12 @@ line.  Return nil if it fails."
         (when skip-fl (forward-line))
 	(while (not (eobp))
 	  (let ((ind (progn (skip-chars-forward " \t") (current-column))))
-	    (cond ((eolp) (delete-region (line-beginning-position) (point)))
-		  ((< ind n) (throw :exit nil))
-		  (t (indent-line-to (- ind n))))
+	    (cond ((< ind n)
+                   (if (eolp) (delete-region (line-beginning-position) (point))
+                     (throw :exit nil)))
+		  (t (delete-region (line-beginning-position)
+                                    (progn (move-to-column n t)
+                                           (point)))))
 	    (forward-line)))
 	;; Signal success.
 	t))))
diff --git a/lisp/org-src.el b/lisp/org-src.el
index f15ba8e99..2beb49e63 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -318,9 +318,6 @@ is 0.")
   "File name associated to Org source buffer, or nil.")
 (put 'org-src-source-file-name 'permanent-local t)
 
-(defvar-local org-src--preserve-blank-line nil)
-(put 'org-src--preserve-blank-line 'permanent-local t)
-
 (defun org-src--construct-edit-buffer-name (org-buffer-name lang)
   "Construct the buffer name for a source editing buffer.
 Format is \"*Org Src ORG-BUFFER-NAME[ LANG ]*\"."
@@ -473,12 +470,15 @@ Assume point is in the corresponding edit buffer."
                      (list (buffer-substring (point-min) eol)
                            (buffer-substring eol (point-max))))))
 	(write-back org-src--allow-write-back)
-        (preserve-blank-line org-src--preserve-blank-line)
-        marker)
+        marker indent-str)
+    (setq indent-str
+          (with-temp-buffer
+            ;; Reproduce indentation parameters from org buffer.
+            (setq indent-tabs-mode use-tabs?)
+            (when (> source-tab-width 0) (setq tab-width source-tab-width))
+            (indent-to indentation-offset)
+            (buffer-string)))
     (with-current-buffer write-back-buf
-      ;; Reproduce indentation parameters from source buffer.
-      (setq indent-tabs-mode use-tabs?)
-      (when (> source-tab-width 0) (setq tab-width source-tab-width))
       ;; Apply WRITE-BACK function on edit buffer contents.
       (insert (org-no-properties (car contents)))
       (setq marker (point-marker))
@@ -488,15 +488,11 @@ Assume point is in the corresponding edit buffer."
       ;; Add INDENTATION-OFFSET to every line in buffer,
       ;; unless indentation is meant to be preserved.
       (when (> indentation-offset 0)
-	(when preserve-fl (forward-line))
+        ;; LaTeX-fragments are inline. Do not add indentation to their
+        ;; first line.
+        (when preserve-fl (forward-line))
         (while (not (eobp))
-	  (skip-chars-forward " \t")
-          (when (or (not (eolp))                               ; not a blank line
-                    (and (eq (point) (marker-position marker)) ; current line
-                         preserve-blank-line))
-	    (let ((i (current-column)))
-	      (delete-region (line-beginning-position) (point))
-	      (indent-to (+ i indentation-offset))))
+          (when (not (eolp)) (insert indent-str)) ; not an empty line
 	  (forward-line)))
       (set-marker marker nil))))
 
@@ -549,11 +545,6 @@ Leave point in edit buffer."
                              (org-element-property :parent datum) nil))
                            (t (org-current-text-indentation)))))
 	     (content-ind org-edit-src-content-indentation)
-             (blank-line (save-excursion (beginning-of-line)
-                                         (looking-at-p "^[[:space:]]*$")))
-             (empty-line (and blank-line (looking-at-p "^$")))
-             (preserve-blank-line (or (and blank-line (not empty-line))
-                                      (and empty-line (= (+ block-ind content-ind) 0))))
 	     (preserve-ind
 	      (and (memq type '(example-block src-block))
 		   (or (org-element-property :preserve-indent datum)
@@ -603,7 +594,6 @@ Leave point in edit buffer."
 	(setq org-src--overlay overlay)
 	(setq org-src--allow-write-back write-back)
 	(setq org-src-source-file-name source-file-name)
-        (setq org-src--preserve-blank-line preserve-blank-line)
 	;; Start minor mode.
 	(org-src-mode)
 	;; Clear undo information so we cannot undo back to the
@@ -637,7 +627,7 @@ Leave point in edit buffer."
   "Fontify code block between START and END using LANG's syntax.
 This function is called by Emacs' automatic fontification, as long
 as `org-src-fontify-natively' is non-nil."
-  (let ((modified (buffer-modified-p)))
+  (let ((modified (buffer-modified-p)) native-tab-width)
     (remove-text-properties start end '(face nil))
     (let ((lang-mode (org-src-get-lang-mode lang)))
       (when (fboundp lang-mode)
@@ -651,6 +641,7 @@ as `org-src-fontify-natively' is non-nil."
 	      ;; Add string and a final space to ensure property change.
 	      (insert string " "))
 	    (unless (eq major-mode lang-mode) (funcall lang-mode))
+            (setq native-tab-width tab-width)
             (font-lock-ensure)
 	    (let ((pos (point-min)) next)
 	      (while (setq next (next-property-change pos))
@@ -708,6 +699,21 @@ as `org-src-fontify-natively' is non-nil."
       (when (or (facep src-face) (listp src-face))
         (font-lock-append-text-property start end 'face src-face))
       (font-lock-append-text-property start end 'face 'org-block))
+    ;; Display native tab indentation characters as spaces
+    (save-excursion
+      (goto-char start)
+      (let ((indent-offset
+	     (if org-src-preserve-indentation 0
+	       (+ (progn (backward-char)
+                         (org-current-text-indentation))
+	          org-edit-src-content-indentation))))
+        (while (re-search-forward "^[ ]*\t" end t)
+          (let* ((b (and (eq indent-offset (move-to-column indent-offset))
+                         (point)))
+                 (e (progn (skip-chars-forward "\t") (point)))
+                 (s (and b (make-string (* (- e b) native-tab-width) ? ))))
+            (when (and b (< b e)) (add-text-properties b e `(display ,s)))
+            (forward-char)))))
     ;; Clear abbreviated link folding.
     (org-fold-region start end nil 'org-link)
     (add-text-properties
diff --git a/lisp/org.el b/lisp/org.el
index 4063ba98f..cda674919 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -19086,21 +19086,14 @@ Also align node properties according to `org-property-format'."
 		     (org-with-point-at (org-element-property :end element)
 		       (skip-chars-backward " \t\n")
 		       (line-beginning-position))))
-             ;; At the beginning of a blank line, do some preindentation.  This
-             ;; signals org-src--edit-element to preserve the indentation on exit
-             (when (and (looking-at-p "^[[:space:]]*$")
-                        (not org-src-preserve-indentation))
-               (let (block-content-ind some-ind)
-                 (org-with-point-at (org-element-property :begin element)
-                   (setq block-content-ind (+ (org-current-text-indentation)
-                                              org-edit-src-content-indentation))
-                   (forward-line)
-		   (save-match-data (re-search-forward "^[ \t]*\\S-" nil t))
-                   (backward-char)
-                   (setq some-ind (if (looking-at-p "#\\+end_src")
-                                      block-content-ind (org-current-text-indentation))))
-                 (indent-line-to (min block-content-ind some-ind))))
-	     (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB")))
+             (let ((block-content-ind
+                    (when (not org-src-preserve-indentation)
+                      (org-with-point-at (org-element-property :begin element)
+                        (+ (org-current-text-indentation)
+                           org-edit-src-content-indentation)))))
+               (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB"))
+               (when (and block-content-ind (looking-at-p "^$"))
+                 (indent-line-to block-content-ind))))
 	    (t
 	     (let ((column (org--get-expected-indentation element nil)))
 	       ;; Preserve current column.
diff --git a/testing/lisp/test-org-src.el b/testing/lisp/test-org-src.el
index 2a45ba66e..c4309ccfc 100644
--- a/testing/lisp/test-org-src.el
+++ b/testing/lisp/test-org-src.el
@@ -304,11 +304,11 @@ This is a tab:\t.
 	(insert " Foo")
 	(org-edit-src-exit)
 	(buffer-string)))))
-  ;; Global indentation obeys `indent-tabs-mode' from the original
-  ;; buffer.
-  (should
+  ;; Global indentation does not obey `indent-tabs-mode' from the
+  ;; original buffer.
+  (should-not
    (string-match-p
-    "^\t+\s*argument2"
+    "\t"
     (org-test-with-temp-text
 	"
 - Item
@@ -323,14 +323,15 @@ This is a tab:\t.
 	(org-edit-special)
 	(org-edit-src-exit)
 	(buffer-string)))))
+  ;; Tab character is preserved
   (should
    (string-match-p
-    "^\s+argument2"
+    "\targument2"
     (org-test-with-temp-text
 	"
 - Item
   #+BEGIN_SRC emacs-lisp<point>
-    (progn\n      (function argument1\n\t\targument2))
+    (progn\n      (function argument1\n    \targument2))
   #+END_SRC"
       (setq-local indent-tabs-mode nil)
       (let ((org-edit-src-content-indentation 2)
@@ -338,43 +339,59 @@ This is a tab:\t.
 	(org-edit-special)
 	(org-edit-src-exit)
 	(buffer-string)))))
-  ;; Global indentation also obeys `tab-width' from original buffer.
+  ;; Indentation does not obey `tab-width' from org buffer.
   (should
    (string-match-p
-    "^\t\\{3\\}\s\\{2\\}argument2"
+    "^  \targument2"
     (org-test-with-temp-text
 	"
-- Item
-  #+BEGIN_SRC emacs-lisp<point>
+#+BEGIN_SRC emacs-lisp
   (progn
-    (function argument1
-              argument2))
-  #+END_SRC"
+    (list argument1\n  \t<point>argument2))
+#+END_SRC"
       (setq-local indent-tabs-mode t)
       (setq-local tab-width 4)
-      (let ((org-edit-src-content-indentation 0)
+      (let ((org-edit-src-content-indentation 2)
 	    (org-src-preserve-indentation nil))
 	(org-edit-special)
+        (setq-local indent-tabs-mode t)
+        (setq-local tab-width 8)
+        (lisp-indent-line)
 	(org-edit-src-exit)
 	(buffer-string)))))
+  ;; Tab characters are displayed with `tab-width' from the native
+  ;; edit buffer.
   (should
-   (string-match-p
-    "^\t\s\\{6\\}argument2"
+   (equal
+    10
     (org-test-with-temp-text
-	"
-- Item
-  #+BEGIN_SRC emacs-lisp<point>
+     "
+#+BEGIN_SRC emacs-lisp
   (progn
-    (function argument1
-              argument2))
-  #+END_SRC"
-      (setq-local indent-tabs-mode t)
-      (setq-local tab-width 8)
-      (let ((org-edit-src-content-indentation 0)
-	    (org-src-preserve-indentation nil))
-	(org-edit-special)
-	(org-edit-src-exit)
-	(buffer-string))))))
+    (list argument1\n  \t<point>argument2))
+#+END_SRC"
+     (setq-local indent-tabs-mode t)
+     (setq-local tab-width 4)
+     (let ((org-edit-src-content-indentation 2)
+	   (org-src-preserve-indentation nil))
+       (font-lock-ensure)
+       (current-column)))))
+  ;; The initial tab characters respect org's `tab-width'.
+  (should
+   (equal
+    10
+    (org-test-with-temp-text
+     "
+#+BEGIN_SRC emacs-lisp
+\t(progn
+\t  (list argument1\n\t\t<point>argument2))
+#+END_SRC"
+     (setq-local indent-tabs-mode t)
+     (setq-local tab-width 2)
+     (let ((org-edit-src-content-indentation 2)
+	   (org-src-preserve-indentation nil))
+       (font-lock-ensure)
+       (current-column))))))
 
 (ert-deftest test-org-src/footnote-references ()
   "Test editing footnote references."
-- 
2.41.0


  reply	other threads:[~2023-07-03 13:51 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-11 22:33 [BUG] Source block indentation does not work properly for yaml-mode [9.6.6 ( @ /home/user/.emacs.d/elpa/org-9.6.6/)] wolf
2023-06-14 12:16 ` Ihor Radchenko
2023-06-17 19:11   ` Sébastien Miquel
2023-06-18 11:16     ` Ihor Radchenko
2023-06-19  8:43       ` Sébastien Miquel
2023-06-19 11:05         ` Ihor Radchenko
2023-06-19 15:32           ` Sébastien Miquel
2023-06-20 10:02             ` Ihor Radchenko
2023-06-21  5:46               ` Sébastien Miquel
2023-06-25 10:46               ` Ihor Radchenko
2023-06-26 11:14               ` Sébastien Miquel
2023-06-26 11:45                 ` Sébastien Miquel
2023-06-26 11:52                 ` Ihor Radchenko
2023-06-26 12:15                   ` Sébastien Miquel
2023-06-26 12:44                     ` Ihor Radchenko
2023-06-27  8:54                       ` Sébastien Miquel
2023-06-28  9:21                         ` Ihor Radchenko
2023-06-29 15:54                           ` Sébastien Miquel
2023-06-30 11:43                             ` Ihor Radchenko
2023-06-30 20:27                               ` Sébastien Miquel
2023-07-01 11:07                                 ` Ihor Radchenko
2023-07-01 17:17                                   ` Sébastien Miquel
2023-07-03  9:58                                     ` Ihor Radchenko
2023-07-03 12:49                                       ` Sébastien Miquel
2023-07-03 13:05                                         ` Ihor Radchenko
2023-07-03 13:48                                           ` Sébastien Miquel [this message]
2023-07-04 10:41                                             ` Ihor Radchenko
2023-07-06 11:01                                               ` Sébastien Miquel
2023-07-07  9:26                                                 ` Ihor Radchenko
2023-07-07  9:54                                                   ` Ihor Radchenko
2023-07-07 13:21                                                     ` Sébastien Miquel
2023-07-08  8:44                                                       ` Ihor Radchenko
2023-07-09 11:10                                                         ` Sébastien Miquel
2023-07-10  8:22                                                           ` Ihor Radchenko
2023-07-07  9:31                                                 ` [BUG] org-list-struct-apply-struct overrides src block indentation (was: [BUG] Source block indentation does not work properly for yaml-mode [9.6.6 ( @ /home/user/.emacs.d/elpa/org-9.6.6/)]) Ihor Radchenko
2023-07-07 13:43                                                   ` Sébastien Miquel
2023-07-08  9:06                                                     ` Ihor Radchenko

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=40b8bf4b-2c1c-ad5b-7109-e0684973bf81@posteo.eu \
    --to=sebastien.miquel@posteo.eu \
    --cc=emacs-orgmode@gnu.org \
    --cc=yantar92@posteo.net \
    /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).