GNU bug report logs -
#74448
30.0.92; c-ts-mode outlines only work with GNU or emacs style
Previous Next
Reported by: Filippo Argiolas <filippo.argiolas <at> gmail.com>
Date: Wed, 20 Nov 2024 22:23:01 UTC
Severity: normal
Found in version 30.0.92
Fixed in version 31.0.50
Done: Juri Linkov <juri <at> linkov.net>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 74448 in the body.
You can then email your comments to 74448 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Wed, 20 Nov 2024 22:23:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Filippo Argiolas <filippo.argiolas <at> gmail.com>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Wed, 20 Nov 2024 22:23:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Hi, I've been playing with the new treesitter based outline minor mode
and c-ts-mode.
It seems that `outline-hide-subtree' is only working properly when code
is formatted with either GNU or emacs style.
To test try it with a function where the function declarator is preceded on the
same line by either type or storage class and type. It will fold the
function heading instead of the function body.
Problem seems `c-ts-mode--outline-predicate' only checks for
function_declarator nodes at the beginning of line (like in GNU coding
style) but other coding style will start the function line with either
storage class (e.g. static) or type.
Something like this seems to work a little better:
(defun c-ts-mode--outline-predicate (node)
"Match outlines on lines with function names."
(or (and (or (equal (treesit-node-type node) "function_declarator")
(equal (treesit-node-type node) "storage_class_specifier")
(equal (treesit-node-type node) "primitive_type")
(equal (treesit-node-type node) "type_identifier"))
(equal (treesit-node-type (treesit-node-parent node))
"function_definition"))
;; DEFUNs in Emacs sources.
(and c-ts-mode-emacs-sources-support
(c-ts-mode--emacs-defun-p node))))
But it kind of breaks GNU style by adding two outlines per function
definition. Also it seems a bit ugly to enumerate all the node types by
hand, there probably is a nicer way to detect a line with a
function_declarator not at bol.
Any better idea?
Thanks,
Filippo
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Thu, 21 Nov 2024 07:46:02 GMT)
Full text and
rfc822 format available.
Message #8 received at 74448 <at> debbugs.gnu.org (full text, mbox):
> Hi, I've been playing with the new treesitter based outline minor mode
> and c-ts-mode.
>
> It seems that `outline-hide-subtree' is only working properly when code
> is formatted with either GNU or emacs style.
>
> To test try it with a function where the function declarator is preceded on the
> same line by either type or storage class and type. It will fold the
> function heading instead of the function body.
>
> Problem seems `c-ts-mode--outline-predicate' only checks for
> function_declarator nodes at the beginning of line (like in GNU coding
> style) but other coding style will start the function line with either
> storage class (e.g. static) or type.
>
> Something like this seems to work a little better:
>
> (defun c-ts-mode--outline-predicate (node)
> "Match outlines on lines with function names."
> (or (and (or (equal (treesit-node-type node) "function_declarator")
> (equal (treesit-node-type node) "storage_class_specifier")
> (equal (treesit-node-type node) "primitive_type")
> (equal (treesit-node-type node) "type_identifier"))
> (equal (treesit-node-type (treesit-node-parent node))
> "function_definition"))
> ;; DEFUNs in Emacs sources.
> (and c-ts-mode-emacs-sources-support
> (c-ts-mode--emacs-defun-p node))))
>
> But it kind of breaks GNU style by adding two outlines per function
> definition. Also it seems a bit ugly to enumerate all the node types by
> hand, there probably is a nicer way to detect a line with a
> function_declarator not at bol.
>
> Any better idea?
Could you please send a few of short examples of each style.
This would help to make a better decision.
And later these examples could be added to tests.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Thu, 21 Nov 2024 09:49:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 74448 <at> debbugs.gnu.org (full text, mbox):
Juri Linkov <juri <at> linkov.net> writes:
>> Hi, I've been playing with the new treesitter based outline minor mode
>> and c-ts-mode.
>>
>> It seems that `outline-hide-subtree' is only working properly when code
>> is formatted with either GNU or emacs style.
>>
>> To test try it with a function where the function declarator is preceded on the
>> same line by either type or storage class and type. It will fold the
>> function heading instead of the function body.
>>
>> Problem seems `c-ts-mode--outline-predicate' only checks for
>> function_declarator nodes at the beginning of line (like in GNU coding
>> style) but other coding style will start the function line with either
>> storage class (e.g. static) or type.
>>
>> Something like this seems to work a little better:
>>
>> (defun c-ts-mode--outline-predicate (node)
>> "Match outlines on lines with function names."
>> (or (and (or (equal (treesit-node-type node) "function_declarator")
>> (equal (treesit-node-type node) "storage_class_specifier")
>> (equal (treesit-node-type node) "primitive_type")
>> (equal (treesit-node-type node) "type_identifier"))
>> (equal (treesit-node-type (treesit-node-parent node))
>> "function_definition"))
>> ;; DEFUNs in Emacs sources.
>> (and c-ts-mode-emacs-sources-support
>> (c-ts-mode--emacs-defun-p node))))
>>
>> But it kind of breaks GNU style by adding two outlines per function
>> definition. Also it seems a bit ugly to enumerate all the node types by
>> hand, there probably is a nicer way to detect a line with a
>> function_declarator not at bol.
>>
>> Any better idea?
>
> Could you please send a few of short examples of each style.
> This would help to make a better decision.
> And later these examples could be added to tests.
You should be able to see it with this example
int bar(void) {
return 1;
}
static int
foo (int bar) {
return 2;
}
int main(void) {
return 3;
}
If you go to the third function and call `outline-hide-subtree' it
replaces the function name with an ellipsis.
Now if you call `outline-show-all' and try to collapse the second
function (GNU style) it will show
foo (int bar) {...
which looks correct to me.
If you show all again and collapse the first one it will do nothing and
say "Before the first heading". This while still showing the outline
icon in the margin.
At the moment I am experimenting with this solution (DEFUN part omitted
for brevity) but it's probably missing some edge case I am not aware of:
(defun c-ts-mode--outline-predicate (node)
"Match outlines on lines with function names."
(when-let* ((decl (treesit-node-child-by-field-name
(treesit-node-parent node) "declarator"))
(node-pos (treesit-node-start node))
(decl-pos (treesit-node-start decl))
(eol (save-excursion (goto-char node-pos) (line-end-position))))
(and (equal (treesit-node-type decl) "function_declarator")
(<= node-pos decl-pos)
(< decl-pos eol))))
Idea is to match a function declarator in the same line as `node' no
matter what node is at bol.
Ciao,
Filippo
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Thu, 21 Nov 2024 18:29:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 74448 <at> debbugs.gnu.org (full text, mbox):
> At the moment I am experimenting with this solution (DEFUN part omitted
> for brevity) but it's probably missing some edge case I am not aware of:
>
> (defun c-ts-mode--outline-predicate (node)
> "Match outlines on lines with function names."
> (when-let* ((decl (treesit-node-child-by-field-name
> (treesit-node-parent node) "declarator"))
> (node-pos (treesit-node-start node))
> (decl-pos (treesit-node-start decl))
> (eol (save-excursion (goto-char node-pos) (line-end-position))))
> (and (equal (treesit-node-type decl) "function_declarator")
> (<= node-pos decl-pos)
> (< decl-pos eol))))
>
> Idea is to match a function declarator in the same line as `node' no
> matter what node is at bol.
Thanks, I confirm your solution is better than the current state.
Hope you could find a common denominator that covers all possible cases.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Fri, 22 Nov 2024 06:03:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 74448 <at> debbugs.gnu.org (full text, mbox):
Juri Linkov <juri <at> linkov.net> writes:
>> At the moment I am experimenting with this solution (DEFUN part omitted
>> for brevity) but it's probably missing some edge case I am not aware of:
>>
>> (defun c-ts-mode--outline-predicate (node)
>> "Match outlines on lines with function names."
>> (when-let* ((decl (treesit-node-child-by-field-name
>> (treesit-node-parent node) "declarator"))
>> (node-pos (treesit-node-start node))
>> (decl-pos (treesit-node-start decl))
>> (eol (save-excursion (goto-char node-pos) (line-end-position))))
>> (and (equal (treesit-node-type decl) "function_declarator")
>> (<= node-pos decl-pos)
>> (< decl-pos eol))))
>>
>> Idea is to match a function declarator in the same line as `node' no
>> matter what node is at bol.
>
> Thanks, I confirm your solution is better than the current state.
> Hope you could find a common denominator that covers all possible cases.
Seems to work with the code I tested. Guess it's still not perfect, if a
function declaration is splitted over multiple lines it will be folded
where the function name is and I think that's what we want.
A minor problem is with GNU style declarations type and storage class
specifier will go in to the previous subtree when you collapse
everything.
But it's probably good enough. As far as I can tell the way it works now
it folds from one outline to the next. The treesitter way would be to
fold up to where the toplevel node ends.
Maybe that's the job for a more specialized treesit folding package and
this is already good for outline-minor-mode.
By the way, the complete defun with Emacs source parsing restored is:
(defun c-ts-mode--outline-predicate (node)
"Match outlines on lines with function names."
(or (when-let* ((decl (treesit-node-child-by-field-name
(treesit-node-parent node) "declarator"))
(node-pos (treesit-node-start node))
(decl-pos (treesit-node-start decl))
(eol (save-excursion (goto-char node-pos) (line-end-position))))
(and (equal (treesit-node-type decl) "function_declarator")
(<= node-pos decl-pos)
(< decl-pos eol)))
;; DEFUNs in Emacs sources.
(and c-ts-mode-emacs-sources-support
(c-ts-mode--emacs-defun-p node))))
Feel free to improve on this if you decide to install it, I never did
the copyright assignment but I think it's trivial enough to enter
without it.
Thanks!
Filippo
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Fri, 22 Nov 2024 07:51:02 GMT)
Full text and
rfc822 format available.
Message #20 received at 74448 <at> debbugs.gnu.org (full text, mbox):
>> Thanks, I confirm your solution is better than the current state.
>> Hope you could find a common denominator that covers all possible cases.
>
> Seems to work with the code I tested. Guess it's still not perfect, if a
> function declaration is splitted over multiple lines it will be folded
> where the function name is and I think that's what we want.
>
> A minor problem is with GNU style declarations type and storage class
> specifier will go in to the previous subtree when you collapse
> everything.
>
> But it's probably good enough. As far as I can tell the way it works now
> it folds from one outline to the next. The treesitter way would be to
> fold up to where the toplevel node ends.
>
> Maybe that's the job for a more specialized treesit folding package and
> this is already good for outline-minor-mode.
outline-minor-mode is designed to always fold from the current heading line
until the next heading line. Maybe outline-minor-mode could be extended
to detach the heading from the outline boundaries. For example,
by adding separate regexps/functions to match outline boundaries
while outline-regexp/outline-search-function will still be used
only for the heading line.
> By the way, the complete defun with Emacs source parsing restored is:
>
> (defun c-ts-mode--outline-predicate (node)
> "Match outlines on lines with function names."
> (or (when-let* ((decl (treesit-node-child-by-field-name
> (treesit-node-parent node) "declarator"))
> (node-pos (treesit-node-start node))
> (decl-pos (treesit-node-start decl))
> (eol (save-excursion (goto-char node-pos) (line-end-position))))
> (and (equal (treesit-node-type decl) "function_declarator")
> (<= node-pos decl-pos)
> (< decl-pos eol)))
> ;; DEFUNs in Emacs sources.
> (and c-ts-mode-emacs-sources-support
> (c-ts-mode--emacs-defun-p node))))
>
>
> Feel free to improve on this if you decide to install it, I never did
> the copyright assignment but I think it's trivial enough to enter
> without it.
Thanks, will test it more before installing.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Fri, 29 Nov 2024 07:39:02 GMT)
Full text and
rfc822 format available.
Message #23 received at 74448 <at> debbugs.gnu.org (full text, mbox):
close 74448 31.0.50
thanks
> Seems to work with the code I tested. Guess it's still not perfect, if a
> function declaration is splitted over multiple lines it will be folded
> where the function name is and I think that's what we want.
>
> A minor problem is with GNU style declarations type and storage class
> specifier will go in to the previous subtree when you collapse
> everything.
Actually this problem exists not only for declarations,
but also for preprocessor directives. For example:
#ifdef HAVE_XDBE
static void
x_set_inhibit_double_buffering (struct frame *f,
Lisp_Object new_value,
Lisp_Object old_value)
a dangling #ifdef will inevitably remain in the previous outline.
And I see no clear way to split such code to outlines
with function declaration headings.
> But it's probably good enough. As far as I can tell the way it works now
> it folds from one outline to the next. The treesitter way would be to
> fold up to where the toplevel node ends.
Probably it would be sufficient to define one additional function
'outline-prefix-function' that will find the beginning of either
the current outline or the next outline.
And it can be called after every call of 'outline-search-function'
to adjust the found position, but only for hiding outlines.
Still not sure if it can theoretically handle all cases.
> Maybe that's the job for a more specialized treesit folding package and
> this is already good for outline-minor-mode.
Indeed, maybe simpler would be to write a new package from scratch,
since the design of outline-minor-mode is too line-oriented.
> By the way, the complete defun with Emacs source parsing restored is:
>
> (defun c-ts-mode--outline-predicate (node)
> "Match outlines on lines with function names."
> (or (when-let* ((decl (treesit-node-child-by-field-name
> (treesit-node-parent node) "declarator"))
> (node-pos (treesit-node-start node))
> (decl-pos (treesit-node-start decl))
> (eol (save-excursion (goto-char node-pos) (line-end-position))))
> (and (equal (treesit-node-type decl) "function_declarator")
> (<= node-pos decl-pos)
> (< decl-pos eol)))
> ;; DEFUNs in Emacs sources.
> (and c-ts-mode-emacs-sources-support
> (c-ts-mode--emacs-defun-p node))))
>
>
> Feel free to improve on this if you decide to install it, I never did
> the copyright assignment but I think it's trivial enough to enter
> without it.
Thanks, this logic makes sense. So after testing more cases I pushed it
to master.
bug marked as fixed in version 31.0.50, send any further explanations to
74448 <at> debbugs.gnu.org and Filippo Argiolas <filippo.argiolas <at> gmail.com>
Request was from
Juri Linkov <juri <at> linkov.net>
to
control <at> debbugs.gnu.org
.
(Fri, 29 Nov 2024 07:39:03 GMT)
Full text and
rfc822 format available.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Fri, 27 Dec 2024 12:24:07 GMT)
Full text and
rfc822 format available.
bug unarchived.
Request was from
Juri Linkov <juri <at> linkov.net>
to
control <at> debbugs.gnu.org
.
(Thu, 30 Jan 2025 07:24:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Thu, 30 Jan 2025 07:30:02 GMT)
Full text and
rfc822 format available.
Message #32 received at 74448 <at> debbugs.gnu.org (full text, mbox):
> Feel free to improve on this if you decide to install it
Hi, Filippo.
Do you remember why we removed this condition from
'c-ts-mode--defun-name':
(equal (treesit-node-type (treesit-node-parent node))
"function_definition")
Without this condition outline headings are added to every single line
of function_declarator, e.g.:
int clusterAddNode(clusterNode *node);
int clusterLoadConfig(char *filename) {
FILE *fp = fopen(filename,"r");
}
=>
(translation_unit
(declaration type: (primitive_type)
declarator:
(function_declarator declarator: (identifier)
...
;)
(function_definition type: (primitive_type)
declarator:
(function_declarator declarator: (identifier)
...
The first function_declarator should not be matched
because it has no function_definition parent.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Sun, 02 Feb 2025 07:58:02 GMT)
Full text and
rfc822 format available.
Message #35 received at 74448 <at> debbugs.gnu.org (full text, mbox):
Juri Linkov <juri <at> linkov.net> writes:
>> Feel free to improve on this if you decide to install it
>
> Hi, Filippo.
>
> Do you remember why we removed this condition from
> 'c-ts-mode--defun-name':
>
> (equal (treesit-node-type (treesit-node-parent node))
> "function_definition")
Hi Juri,
Sorry for the late reply!
Don't remember the exact reason, seems a mistake looking at it
now. Probably got lost while trying to find a good matcher for
declarators and didn't have stand-alone prototypes in my test case to
show the issue.
I'd say to restore that check. Did a brief test here and it does not
seem to break anything else.
Filippo
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Tue, 11 Feb 2025 17:46:02 GMT)
Full text and
rfc822 format available.
Message #38 received at 74448 <at> debbugs.gnu.org (full text, mbox):
>> Do you remember why we removed this condition from
>> 'c-ts-mode--defun-name':
>>
>> (equal (treesit-node-type (treesit-node-parent node))
>> "function_definition")
>
> Don't remember the exact reason, seems a mistake looking at it
> now. Probably got lost while trying to find a good matcher for
> declarators and didn't have stand-alone prototypes in my test case to
> show the issue.
>
> I'd say to restore that check. Did a brief test here and it does not
> seem to break anything else.
Now 'treesit-outline-search' was fixed that allowed
to simplify 'c-ts-mode--defun-name' and also handle
the case with "pointer_declarator" between "function_definition"
and "function_declarator".
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74448
; Package
emacs
.
(Thu, 13 Feb 2025 06:03:02 GMT)
Full text and
rfc822 format available.
Message #41 received at 74448 <at> debbugs.gnu.org (full text, mbox):
Juri Linkov <juri <at> linkov.net> writes:
>>> Do you remember why we removed this condition from
>>> 'c-ts-mode--defun-name':
>>>
>>> (equal (treesit-node-type (treesit-node-parent node))
>>> "function_definition")
>>
>> Don't remember the exact reason, seems a mistake looking at it
>> now. Probably got lost while trying to find a good matcher for
>> declarators and didn't have stand-alone prototypes in my test case to
>> show the issue.
>>
>> I'd say to restore that check. Did a brief test here and it does not
>> seem to break anything else.
>
> Now 'treesit-outline-search' was fixed that allowed
> to simplify 'c-ts-mode--defun-name' and also handle
> the case with "pointer_declarator" between "function_definition"
> and "function_declarator".
Looks good to me, thanks for working on this!
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Thu, 13 Mar 2025 11:24:20 GMT)
Full text and
rfc822 format available.
This bug report was last modified today.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.