Re: [O] [RFC] Rewrite indentation functions
Hello, Bastien writes: > Please go ahead, that's the easiest way to get more feedback and Eric > did half the job already, so we must be good. Applied. Regards, -- Nicolas Goaziou
Re: [O] [RFC] Rewrite indentation functions
Bastien writes: > Hi Nicolas, > > Nicolas Goaziou writes: > >> I would like to install the following patches on master. > > Please go ahead, that's the easiest way to get more feedback and Eric > did half the job already, so we must be good. > > Thanks for working on this, I've been running all the three new versions of the patches for a few days now, and haven't succeeded in breaking anything!
Re: [O] [RFC] Rewrite indentation functions
Hi Nicolas, Nicolas Goaziou writes: > I would like to install the following patches on master. Please go ahead, that's the easiest way to get more feedback and Eric did half the job already, so we must be good. Thanks for working on this, -- Bastien
Re: [O] [RFC] Rewrite indentation functions
Hello, Eric Abrahamsen writes: > One last thing! In the course of this I also noticed that, in a buffer > that contains a broken property drawer, you can't set properties on > *any* other heading. When `org-buffer-property-keys' goes looking for > valid keys used elsewhere in the current buffer, it calls > `org-get-property-block' on the broken drawer, and errors when that > function returns nil. > > I tried changing the call to (org-get-property-block nil nil t), and > that seems to solve it: at least the broken drawer is repaired, and I > can successfully set properties. Dunno if that's the right way to handle > it, though. IIUC, this problem is unrelated to indentation. Would you mind starting a new thread for this, with an ECM? Thank you. Regards, -- Nicolas Goaziou
Re: [O] [RFC] Rewrite indentation functions
Eric Abrahamsen writes: > Perhaps we need a new version of patch 3? Here it is. Regards, -- Nicolas Goaziou >From 66d0ab7d1025969e5fd383b93ffe1fb1b05a83a8 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Mon, 28 Apr 2014 18:38:31 +0200 Subject: [PATCH 3/3] Rewrite `org-indent-drawer' and `org-indent-block' * lisp/org.el (org-indent-block, org-indent-drawer): Rewrite functions. --- lisp/org.el | 75 - 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index af34d99..e8d6fa9 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -22382,47 +22382,6 @@ Also align node properties according to `org-property-format'." (org--align-node-property) (org-move-to-column column) -(defun org-indent-drawer () - "Indent the drawer at point." - (interactive) - (let ((p (point)) - (e (and (save-excursion (re-search-forward ":END:" nil t)) - (match-end 0))) - (folded - (save-excursion - (end-of-line) - (when (overlays-at (point)) - (member 'invisible (overlay-properties - (car (overlays-at (point) -(when folded (org-cycle)) -(indent-for-tab-command) -(while (and (move-beginning-of-line 2) (< (point) e)) - (indent-for-tab-command)) -(goto-char p) -(when folded (org-cycle))) - (message "Drawer at point indented")) - -(defun org-indent-block () - "Indent the block at point." - (interactive) - (let ((p (point)) - (case-fold-search t) - (e (and (save-excursion (re-search-forward "#\\+end_?\\(?:[a-z]+\\)?" nil t)) - (match-end 0))) - (folded - (save-excursion - (end-of-line) - (when (overlays-at (point)) - (member 'invisible (overlay-properties - (car (overlays-at (point) -(when folded (org-cycle)) -(indent-for-tab-command) -(while (and (move-beginning-of-line 2) (< (point) e)) - (indent-for-tab-command)) -(goto-char p) -(when folded (org-cycle))) - (message "Block at point indented")) - (defun org-indent-region (start end) "Indent each non-blank line in the region. Called from a program, START and END specify the region to @@ -22520,6 +22479,40 @@ assumed to be significant there." (set-marker element-end nil (set-marker end nil +(defun org-indent-drawer () + "Indent the drawer at point." + (interactive) + (unless (save-excursion + (beginning-of-line) + (org-looking-at-p org-drawer-regexp)) +(user-error "Not at a drawer")) + (let ((element (org-element-at-point))) +(unless (memq (org-element-type element) '(drawer property-drawer)) + (user-error "Not at a drawer")) +(org-with-wide-buffer + (org-indent-region (org-element-property :begin element) + (org-element-property :end element + (message "Drawer at point indented")) + +(defun org-indent-block () + "Indent the block at point." + (interactive) + (unless (save-excursion + (beginning-of-line) + (let ((case-fold-search t)) + (org-looking-at-p "[ \t]*#\\+\\(begin\\|end\\)_"))) +(user-error "Not at a block")) + (let ((element (org-element-at-point))) +(unless (memq (org-element-type element) + '(comment-block center-block example-block export-block + quote-block special-block src-block + verse-block)) + (user-error "Not at a block")) +(org-with-wide-buffer + (org-indent-region (org-element-property :begin element) + (org-element-property :end element + (message "Block at point indented")) + ;;; Filling -- 1.9.2
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > Hello, > > Eric Abrahamsen writes: > >>> Right now I'm seeing breakage with `org-set-property' -- this only >>> happens on the indentation patches branch. Adding an EXPORT_AUTHOR >>> property with that command, value of "asdfadsf", gives me this: >>> >>> * Test Heading >>> :PROPERTIES: >>> >>> :EXPORT_AUTHOR: asdfasdfnilnil >>> >>> Extra blank nil, spurious "nils", and no :END: One last thing! In the course of this I also noticed that, in a buffer that contains a broken property drawer, you can't set properties on *any* other heading. When `org-buffer-property-keys' goes looking for valid keys used elsewhere in the current buffer, it calls `org-get-property-block' on the broken drawer, and errors when that function returns nil. I tried changing the call to (org-get-property-block nil nil t), and that seems to solve it: at least the broken drawer is repaired, and I can successfully set properties. Dunno if that's the right way to handle it, though. Eric
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > Hello, > > Eric Abrahamsen writes: > >>> Right now I'm seeing breakage with `org-set-property' -- this only >>> happens on the indentation patches branch. Adding an EXPORT_AUTHOR >>> property with that command, value of "asdfadsf", gives me this: >>> >>> * Test Heading >>> :PROPERTIES: >>> >>> :EXPORT_AUTHOR: asdfasdfnilnil >>> >>> Extra blank nil, spurious "nils", and no :END: > > [...] > >> Specifically, in this section of `org-indent-line': >> >> (when (eq type 'node-property) >> (let ((column (current-column))) >> (save-excursion >> (beginning-of-line) >> (looking-at org-property-re)) >> (replace-match (concat (match-string 4) >> (format org-property-format >> (match-string 1) >> (match-string 3))) >> t t) >> (org-move-to-column column))) >> >> Those match-string calls toward the end both return "nil", and the >> "nil"s get inserted directly into the buffer. I tried this with a >> minimal setup (load-paths only, and a blank Org file) and could >> reproduce. > > Indeed. I attach a replacement for both patch 1 and 2. One other thing: I was going to poke around with code block indentation and see if I could break it, but I can't get the third patch to apply cleanly any more. I don't know if it's because I rebased this testing branch against an update master, or if your changes to the first two patches mean the third needs to be edited accordingly... It fails at org.el:22368, which is this line inside `org-indent-line': (skip-chars-backward " \r\t\n") Perhaps we need a new version of patch 3? Eric
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > Hello, > > Eric Abrahamsen writes: > >>> Right now I'm seeing breakage with `org-set-property' -- this only >>> happens on the indentation patches branch. Adding an EXPORT_AUTHOR >>> property with that command, value of "asdfadsf", gives me this: >>> >>> * Test Heading >>> :PROPERTIES: >>> >>> :EXPORT_AUTHOR: asdfasdfnilnil >>> >>> Extra blank nil, spurious "nils", and no :END: > > [...] > >> Specifically, in this section of `org-indent-line': >> >> (when (eq type 'node-property) >> (let ((column (current-column))) >> (save-excursion >> (beginning-of-line) >> (looking-at org-property-re)) >> (replace-match (concat (match-string 4) >> (format org-property-format >> (match-string 1) >> (match-string 3))) >> t t) >> (org-move-to-column column))) >> >> Those match-string calls toward the end both return "nil", and the >> "nil"s get inserted directly into the buffer. I tried this with a >> minimal setup (load-paths only, and a blank Org file) and could >> reproduce. > > Indeed. I attach a replacement for both patch 1 and 2. Looks good! Nothing else to report so far...
Re: [O] [RFC] Rewrite indentation functions
Hello, Eric Abrahamsen writes: >> Right now I'm seeing breakage with `org-set-property' -- this only >> happens on the indentation patches branch. Adding an EXPORT_AUTHOR >> property with that command, value of "asdfadsf", gives me this: >> >> * Test Heading >> :PROPERTIES: >> >> :EXPORT_AUTHOR: asdfasdfnilnil >> >> Extra blank nil, spurious "nils", and no :END: [...] > Specifically, in this section of `org-indent-line': > > (when (eq type 'node-property) > (let ((column (current-column))) >(save-excursion > (beginning-of-line) > (looking-at org-property-re)) >(replace-match (concat (match-string 4) > (format org-property-format > (match-string 1) > (match-string 3))) > t t) >(org-move-to-column column))) > > Those match-string calls toward the end both return "nil", and the > "nil"s get inserted directly into the buffer. I tried this with a > minimal setup (load-paths only, and a blank Org file) and could > reproduce. Indeed. I attach a replacement for both patch 1 and 2. Thank you. Regards, -- Nicolas Goaziou >From 104a091d127b746662adfa7b3f71a602ef5f816e Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Tue, 24 Dec 2013 14:04:17 +0100 Subject: [PATCH 1/3] Rewrite `org-indent-line' * lisp/org.el (org--get-expected-indentation, org--align-node-property): New functions. (org-indent-line): Use new function. Also merge functionalities with `org-src-native-tab-command-maybe'. * lisp/org-src.el (org-src-native-tab-command-maybe): Remove function. * testing/lisp/test-org.el (test-org/indent-line): New test. --- lisp/org-src.el | 11 -- lisp/org.el | 281 +-- testing/lisp/test-org.el | 157 ++ 3 files changed, 330 insertions(+), 119 deletions(-) diff --git a/lisp/org-src.el b/lisp/org-src.el index 791f934..8d60f68 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -895,17 +895,6 @@ issued in the language major mode buffer." :version "24.1" :group 'org-babel) -(defun org-src-native-tab-command-maybe () - "Perform language-specific TAB action. -Alter code block according to what TAB does in the language major mode." - (and org-src-tab-acts-natively - (org-in-src-block-p) - (not (equal this-command 'org-shifttab)) - (let ((org-src-strip-leading-and-trailing-blank-lines nil)) - (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB") - -(add-hook 'org-tab-first-hook 'org-src-native-tab-command-maybe) - (defun org-src-font-lock-fontify-block (lang start end) "Fontify code block. This function is called by emacs automatic fontification, as long diff --git a/lisp/org.el b/lisp/org.el index 44a4e44..3559209 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -22206,116 +22206,181 @@ hierarchy of headlines by UP levels before marking the subtree." ;;; Indentation +(defun org--get-expected-indentation (element contentsp) + "Expected indentation column for current line, according to ELEMENT. +ELEMENT is an element containing point. CONTENTSP is non-nil +when indentation is to be computed according to contents of +ELEMENT." + (let ((type (org-element-type element)) + (start (org-element-property :begin element))) +(org-with-wide-buffer + (cond + (contentsp + (case type + (footnote-definition 0) + ((headline inlinetask nil) + (if (not org-adapt-indentation) 0 + (let ((level (org-current-level))) + (if level (1+ level) 0 + ((item plain list) + (org-list-item-body-column + (or (org-element-property :post-affiliated element) start))) + (otherwise + (goto-char start) + (org-get-indentation + ((memq type '(headline inlinetask nil)) + (if (save-excursion (beginning-of-line) (looking-at "[ \t]*$")) + (org--get-expected-indentation element t) + 0)) + ((eq type 'footnote-definition) 0) + ;; First paragraph of a footnote definition or an item. + ;; Indent like parent. + ((< (line-beginning-position) start) + (org--get-expected-indentation + (org-element-property :parent element) t)) + ;; At first line: indent according to previous sibling, if any, + ;; ignoring footnote definitions and inline tasks, or parent's + ;; contents. + ((= (line-beginning-position) start) + (catch 'exit + (while t + (if (= (point-min) start) (throw 'exit 0) + (goto-char (1- start)) + (let ((previous (org-element-at-point))) + (while (let ((parent (org-element-property :parent previous))) + (and parent + (setq previous parent) + (<= (org-element-property :end parent) start + (cond ((or (not previous) + (> (org-element-property :end previous) start)) + (throw 'exit (org--ge
Re: [O] [RFC] Rewrite indentation functions
Eric Abrahamsen writes: > Nicolas Goaziou writes: > >> Hello, >> >> Eric Abrahamsen writes: >> >>> Wish I was competent to actually review this, but... In lieu of that, >>> I'd be happy to run it and report errors. If you think a separate >>> testing branch is warranted, that might be an idea. Otherwise I'd say >>> let it drop and we'll pick up the pieces :) >> >> You can create a local branch in your git repo and apply the patches >> I sent (be sure to use the second version of the first patch) there. >> >> I can certainly wait for your feedback. If it turns out to be mostly >> good and no one objects, I will then apply the patches and fix the >> remnant issues on master branch. > > Hi Nicolas, > > Right now I'm seeing breakage with `org-set-property' -- this only > happens on the indentation patches branch. Adding an EXPORT_AUTHOR > property with that command, value of "asdfadsf", gives me this: > > * Test Heading > :PROPERTIES: > > :EXPORT_AUTHOR: asdfasdfnilnil > > Extra blank nil, spurious "nils", and no :END: > > I'm starting dinner and won't be able to go spelunking right now. I'll > get to soon, if you aren't seeing this, or don't sort it out first. > > Eric Specifically, in this section of `org-indent-line': (when (eq type 'node-property) (let ((column (current-column))) (save-excursion (beginning-of-line) (looking-at org-property-re)) (replace-match (concat (match-string 4) (format org-property-format (match-string 1) (match-string 3))) t t) (org-move-to-column column))) Those match-string calls toward the end both return "nil", and the "nil"s get inserted directly into the buffer. I tried this with a minimal setup (load-paths only, and a blank Org file) and could reproduce. E
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > Hello, > > Eric Abrahamsen writes: > >> Wish I was competent to actually review this, but... In lieu of that, >> I'd be happy to run it and report errors. If you think a separate >> testing branch is warranted, that might be an idea. Otherwise I'd say >> let it drop and we'll pick up the pieces :) > > You can create a local branch in your git repo and apply the patches > I sent (be sure to use the second version of the first patch) there. > > I can certainly wait for your feedback. If it turns out to be mostly > good and no one objects, I will then apply the patches and fix the > remnant issues on master branch. Hi Nicolas, Right now I'm seeing breakage with `org-set-property' -- this only happens on the indentation patches branch. Adding an EXPORT_AUTHOR property with that command, value of "asdfadsf", gives me this: * Test Heading :PROPERTIES: :EXPORT_AUTHOR: asdfasdfnilnil Extra blank nil, spurious "nils", and no :END: I'm starting dinner and won't be able to go spelunking right now. I'll get to soon, if you aren't seeing this, or don't sort it out first. Eric
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > Hello, > > Eric Abrahamsen writes: > >> Wish I was competent to actually review this, but... In lieu of that, >> I'd be happy to run it and report errors. If you think a separate >> testing branch is warranted, that might be an idea. Otherwise I'd say >> let it drop and we'll pick up the pieces :) > > You can create a local branch in your git repo and apply the patches > I sent (be sure to use the second version of the first patch) there. > > I can certainly wait for your feedback. If it turns out to be mostly > good and no one objects, I will then apply the patches and fix the > remnant issues on master branch. Done! I'll try to give it a little exercise over the next couple of days, though I guess I'm not expecting much breakage.
Re: [O] [RFC] Rewrite indentation functions
Hello, Eric Abrahamsen writes: > Wish I was competent to actually review this, but... In lieu of that, > I'd be happy to run it and report errors. If you think a separate > testing branch is warranted, that might be an idea. Otherwise I'd say > let it drop and we'll pick up the pieces :) You can create a local branch in your git repo and apply the patches I sent (be sure to use the second version of the first patch) there. I can certainly wait for your feedback. If it turns out to be mostly good and no one objects, I will then apply the patches and fix the remnant issues on master branch. Thank you. Regards, -- Nicolas Goaziou
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > Hello, > > I would like to install the following patches on master. Basically, they > consist of a full rewrite of all indentation related functions, with > explicit rules in docstrings, comprehensive test suites, and backed-up > by the parser. Wish I was competent to actually review this, but... In lieu of that, I'd be happy to run it and report errors. If you think a separate testing branch is warranted, that might be an idea. Otherwise I'd say let it drop and we'll pick up the pieces :) > The following changes in `org-indent-line' are expected: > > 1. Indentation of the first line of an element should be, when > applicable, relative to the /first line/ of the element before. > Therefore, in the following example > > Some long paragraph >with multiple line > >XAnother paragraph > > indenting line starting with "X" will align it with "Some", not > "with". This is consistent with plain lists > > - A list with some >long paragraph > >XAnother paragraph > > where last line should be indented like "-", not "long". > > 2. It should be possible to indent example block, verse block or > export block contents, as `org-indent-line' usually happens on > behalf of the user, who is assumed to know what he is doing. > > Though, this will not be the case in `org-indent-region', as > changes could happen without the user knowing about it (e.g., when > indenting a complete, mostly hidden, buffer). > > 3. It should be possible to indent fixed-width areas. > > `org-indent-region' also applies on hidden lines, with a few exceptions, > as explained above. Also, it should be a lot faster when > `org-src-tab-acts-natively' is non-nil, and complete without errors. It > could be made faster, but the main bottleneck in this function is now > `org-edit-src-code', which will need to be revamped at some point. > > Internally, `org-src-native-tab-command-maybe' is merged into > `org-indent-line' since this should be a core feature, not something > installed via a hook. > > > WDYT? > > > Regards,
Re: [O] [RFC] Rewrite indentation functions
Nicolas Goaziou writes: > I would like to install the following patches on master. Basically, they > consist of a full rewrite of all indentation related functions, with > explicit rules in docstrings, comprehensive test suites, and backed-up > by the parser. Here's an update for the first patch, in order to fix behaviour after a footnote definition or an inline task. More specifically, in the following example, * Headline Some [fn:1] Definition XParagraph line with point at "X" should be indented like "Some", since it doesn't belong to the footnote definition. Regards, -- Nicolas Goaziou >From 283588780f3ee64c87b336ff65fc758047687923 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Tue, 24 Dec 2013 14:04:17 +0100 Subject: [PATCH 1/3] Rewrite `org-indent-line' * lisp/org.el (org--get-expected-indentation): New function. (org-indent-line): Use new function. Also merge functionalities with `org-src-native-tab-command-maybe'. * lisp/org-src.el (org-src-native-tab-command-maybe): Remove function. * testing/lisp/test-org.el (test-org/indent-line): New test. --- lisp/org-src.el | 11 -- lisp/org.el | 273 --- testing/lisp/test-org.el | 143 + 3 files changed, 308 insertions(+), 119 deletions(-) diff --git a/lisp/org-src.el b/lisp/org-src.el index 791f934..8d60f68 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -895,17 +895,6 @@ issued in the language major mode buffer." :version "24.1" :group 'org-babel) -(defun org-src-native-tab-command-maybe () - "Perform language-specific TAB action. -Alter code block according to what TAB does in the language major mode." - (and org-src-tab-acts-natively - (org-in-src-block-p) - (not (equal this-command 'org-shifttab)) - (let ((org-src-strip-leading-and-trailing-blank-lines nil)) - (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB") - -(add-hook 'org-tab-first-hook 'org-src-native-tab-command-maybe) - (defun org-src-font-lock-fontify-block (lang start end) "Fontify code block. This function is called by emacs automatic fontification, as long diff --git a/lisp/org.el b/lisp/org.el index 44a4e44..3db6e86 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -22206,116 +22206,173 @@ hierarchy of headlines by UP levels before marking the subtree." ;;; Indentation +(defun org--get-expected-indentation (element contentsp) + "Expected indentation column for current line, according to ELEMENT. +ELEMENT is an element containing point. CONTENTSP is non-nil +when indentation is to be computed according to contents of +ELEMENT." + (let ((type (org-element-type element)) + (start (org-element-property :begin element))) +(org-with-wide-buffer + (cond + (contentsp + (case type + (footnote-definition 0) + ((headline inlinetask nil) + (if (not org-adapt-indentation) 0 + (let ((level (org-current-level))) + (if level (1+ level) 0 + ((item plain list) + (org-list-item-body-column + (or (org-element-property :post-affiliated element) start))) + (otherwise + (goto-char start) + (org-get-indentation + ((memq type '(footnote-definition headline inlinetask nil)) 0) + ;; First paragraph of a footnote definition or an item. + ;; Indent like parent. + ((< (line-beginning-position) start) + (org--get-expected-indentation + (org-element-property :parent element) t)) + ;; At first line: indent according to previous sibling, if any, + ;; ignoring footnote definitions and inline tasks, or parent's + ;; contents. + ((= (line-beginning-position) start) + (catch 'exit + (while t + (if (= (point-min) start) (throw 'exit 0) + (goto-char (1- start)) + (let ((previous (org-element-at-point))) + (while (let ((parent (org-element-property :parent previous))) + (and parent + (setq previous parent) + (<= (org-element-property :end parent) start + (cond ((or (not previous) + (> (org-element-property :end previous) start)) + (throw 'exit (org--get-expected-indentation previous t))) + ((memq (org-element-type previous) + '(footnote-definition inlinetask)) + (setq start (org-element-property :begin previous))) + (t (goto-char (org-element-property :begin previous)) + (throw 'exit (org-get-indentation) + ;; Otherwise, move to the first non-blank line above. + (t + (beginning-of-line) + (let ((pos (point))) + (skip-chars-backward " \r\t\n") + (cond + ;; Two blank lines end a footnote definition or a plain + ;; list. When we indent an empty line after them, the + ;; containing list or footnote definition is over, so it + ;; qualifies as a previous sibling. Therefore, we indent + ;; like its first line. + ((and (memq type '(footnote-definition plain-list)) + (> (count-lines (point) pos) 2)) + (goto-char start) + (or
Re: [O] [RFC] Rewrite indentation functions
Vikas Rawal wrote: >> >> 1. Indentation of the first line of an element should be, when >> applicable, relative to the /first line/ of the element before. >> Therefore, in the following example >> >> Some long paragraph >> with multiple line >> >> XAnother paragraph >> > > It is almost surely something that you must have thought of. > > You seem to be using X as a special character. What if a paragraph > starts with X? Would you want to use a double X? > > It does not seem very elegant to use X. Would it break ispell? Can we > have a space between X and the actual first word of the paragraph (as > we do with *s for headlines and -/+ for lists)? And could one use > another character? IIUC, you miss the legend "X = position of cursor"... Best regards, Seb -- Sebastien Vauban
Re: [O] [RFC] Rewrite indentation functions
> > 1. Indentation of the first line of an element should be, when > applicable, relative to the /first line/ of the element before. > Therefore, in the following example > > Some long paragraph > with multiple line > > XAnother paragraph > It is almost surely something that you must have thought of. You seem to be using X as a special character. What if a paragraph starts with X? Would you want to use a double X? It does not seem very elegant to use X. Would it break ispell? Can we have a space between X and the actual first word of the paragraph (as we do with *s for headlines and -/+ for lists)? And could one use another character? Vikas