After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 736727 - Smart indentation
Smart indentation
Status: RESOLVED OBSOLETE
Product: gtksourceview
Classification: Platform
Component: General
unspecified
Other All
: Normal enhancement
: ---
Assigned To: GTK Sourceview maintainers
GTK Sourceview maintainers
: 107044 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2014-09-16 09:12 UTC by Christian Hergert
Modified: 2020-11-13 23:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
sourceview: compute auto-indentation text in signal handler. (2.97 KB, patch)
2014-09-16 09:12 UTC, Christian Hergert
none Details | Review
sourceview: add ::query-auto-indent signal to compute indentation text (2.96 KB, patch)
2014-09-16 09:35 UTC, Christian Hergert
none Details | Review
sourceview: add ::query-auto-indent signal to compute indentation text (2.98 KB, patch)
2014-09-16 20:57 UTC, Christian Hergert
none Details | Review

Description Christian Hergert 2014-09-16 09:12:34 UTC
It would be handy to be able to override the default auto-indent rules. This
would allow for languages such as C to be a bit more accurate with tab and
spacing placement.

For example, currently after a multi-line C comment, the following line will
be auto indented one character too far in.

The attached patches allow for a custom indent handler to be attached.
Comment 1 Christian Hergert 2014-09-16 09:12:36 UTC
Created attachment 286270 [details] [review]
sourceview: compute auto-indentation text in signal handler.

This allows for consumers of GtkSourceView to implement
GtkSourceView::compute-indentation and override the default behavior.
This is useful for providing language specific indentation rules.

Since there is no padding in GtkSourceView, no class vfunc is provided.
The first handler simply wins.
Comment 2 Ignacio Casal Quinteiro (nacho) 2014-09-16 09:16:31 UTC
nice. We had this in the todo list for some time already since we wanted to use it in the code assistance. Maybe we should unify the indentation code in some library or something?
Comment 3 jessevdk@gmail.com 2014-09-16 09:19:14 UTC
Note that the same effect can be achieved as we do in gca [1][2], by connecting to event-after and handling key-presses after they have been handled by gsv. Although I think the signal you propose is much cleaner already, but it's not a universal solution for smart-indenting. If we are going to add more API to gsv for this kind of thing, it might be worth thinking about the larger solution (i.e. smart-indenting) so we can keep the API clean.

[1] https://git.gnome.org/browse/gedit-code-assistance/tree/src/gca-view.vala#n313
[2] https://git.gnome.org/browse/gedit-code-assistance/tree/indentbackends/c/gca-c-backend.vala
Comment 4 jessevdk@gmail.com 2014-09-16 09:26:40 UTC
Review of attachment 286270 [details] [review]:

::: gtksourceview/gtksourceview.c
@@ +601,3 @@
 
+	/**
+	 * GtkSourceView::compute-indentation:

I'm not sure this is the best name, it's specific to auto-indent. Maybe call it query-auto-indent?

@@ +622,3 @@
+			      g_signal_accumulator_first_wins,
+			      NULL,
+	 * This will only be emitted if GtkSourceView:auto-indent is set to

Is this best practice now? I would still go with generated marshals from a list, to avoid going through libffi to emit signals.
Comment 5 Christian Hergert 2014-09-16 09:30:59 UTC
Review of attachment 286270 [details] [review]:

::: gtksourceview/gtksourceview.c
@@ +601,3 @@
 
+	/**
+	 * GtkSourceView::compute-indentation:

"query-auto-indent" sounds find by me. Feels similar to say "query-tooltip".

@@ +622,3 @@
+			      g_signal_accumulator_first_wins,
+			      NULL,
+			      g_cclosure_marshal_generic,

The one above it passes NULL for the marshaler, I thought I'd be more specific. But in both cases I believe generic is used. I'm okay with generating a marshaler though.
Comment 6 Christian Hergert 2014-09-16 09:35:29 UTC
Created attachment 286272 [details] [review]
sourceview: add ::query-auto-indent signal to compute indentation text

This allows for consumers of GtkSourceView to implement custom
indentation routines to override the default auto-indent behavior.
This is useful for providing language specific indentation rules.

Since there is no padding in GtkSourceView, no class vfunc is provided.
The first handler wins.
Comment 7 jessevdk@gmail.com 2014-09-16 09:36:15 UTC
Review of attachment 286270 [details] [review]:

::: gtksourceview/gtksourceview.c
@@ +622,3 @@
+			      g_signal_accumulator_first_wins,
+			      NULL,
+	 * This will only be emitted if GtkSourceView:auto-indent is set to

Ah ok! didn't know that, I thought actually that NULL meant the default empty arg/retval marshaller :) I guess it's fine then to leave it as is.
Comment 8 Christian Hergert 2014-09-16 09:40:44 UTC
Jesse, Do you think anything additional is needed to be able to do custom language support?

I think it makes sense to have a library that can do more of the language-specific features so that code can be shared, but in particular I'm curious if you have a suggestion based on implementing gedit-code-assistance what other stuff would be helpful here.

I certainly wouldn't mind something similar to GtkSourceLanguage for this in GSV either.
Comment 9 Sébastien Wilmet 2014-09-16 09:42:52 UTC
I've replaced all the generated marshallers by NULL to use the generic marshaller, it's simpler. Creating a new signal is already painful enough.
Comment 10 jessevdk@gmail.com 2014-09-16 09:54:22 UTC
We have thought about smart-indenting in gsv for quite some time, but never settled on a satisfactory solution. Ideally I wanted to be able to specify indentation rules in the lang files, similar to how other editors do this (like sublime). @nacho knows more about this, since he tried implementing it :) In the end however, in gca we went more with the vim way, i.e. not doing it declaratively. I think it works quite well, and might actually be easier/more flexible in the end than writing regex rules.

We could think about merging the gca indent backends into gsv in the next cycle, it shouldn't be too much work to do so. Maybe @nacho can comment more on the details, it's his work.
Comment 11 Ignacio Casal Quinteiro (nacho) 2014-09-16 09:58:42 UTC
In my opinion gsv is definetly the right place. And I still think the vim way is the "right" way at least for some languages. One way could be to have a generic regex backend which would use the language regex rules, and for other languages where we need triggers etc to have the specific backend as we do right now in gsv.

The main problem here is the pain that is to write everything in C, though we did it for gca in vala so it should be feasible.
Comment 12 jessevdk@gmail.com 2014-09-16 10:06:11 UTC
We could also think about using libpeas in gsv.
Comment 13 Sébastien Wilmet 2014-09-16 12:08:32 UTC
It's easier to first have an internal API with one backend for C-like languages.
If people want to write external backend (with the API, or in .lang files), we can think about that later, and in the meantime there can be several iterations on the internal API if needed.
Comment 14 Christian Hergert 2014-09-16 19:42:12 UTC
What do you all think about using this "query-auto-indent" signal, and then in the default handler hook that up to an internal implementation for C like languages?

That would allow us to iterate on the implementation, while still allowing for external use in the mean time. In particularly, that would let me play with things in Builder easier. (Easier for me to have people test Builder if it doesn't require jhbuild, although I guess we are probably past that point now).
Comment 15 Sébastien Wilmet 2014-09-16 20:01:33 UTC
Sounds good.

The list of supported languages would be hardcoded, so only certain GtkSourceLanguage's would enable the custom auto-indent.
Comment 16 Christian Hergert 2014-09-16 20:57:49 UTC
Created attachment 286325 [details] [review]
sourceview: add ::query-auto-indent signal to compute indentation text

This allows for consumers of GtkSourceView to implement custom
indentation routines to override the default auto-indent behavior.
This is useful for providing language specific indentation rules.

Since there is no padding in GtkSourceView, no class vfunc is provided.
The first handler wins.
Comment 17 Christian Hergert 2014-09-16 20:58:48 UTC
I just tried wiring this up. Looks like connect_after() is needed since otherwise the default handler will get called. Too bad we don't have padding in GtkSourceView for a class vfunc.
Comment 18 Christian Hergert 2014-09-16 21:14:56 UTC
One of the other things it would be nice to do is to recompute the indent after trigger characters. For example:

  if (foo)
    {
      item1();
      item2();
      }

      ^ this should trigger recomputation and unindent 2.
Comment 19 Paolo Borelli 2014-09-17 06:17:41 UTC
My original idea for this was something along these lines:

 - a GtkSourceIndenter interface
 - a GtkSourceCIndenter class that implements the interface for C like languages
 - eventually other indenter classes (e.g. a generic one based on regexes)
 - (maybe) factor out the current code that indents to the same level into a DummmyIndenter (this is not really needed, but the refactoring would help us validate the api)
 - GtkSourceView would expose API to register an indenter
 - GtkSourceView would call the indenter methods when inserting a new line
 - lang files would use the metadata section to define their indenter
 - lang files would use the metadata section to define extra triggers

This is all very hand-wavy... here are a some open questions:

 - should the methods of the interface manipulate the buffer or should they return an indentation level and let the caller to the actual modification?
 - is defining triggers statically in the lang files enough or do we need an api to registers triggers dynamically
Comment 20 Paolo Borelli 2014-09-17 06:20:42 UTC
FWIW indentation support is the oldest open bug against GSV :)

See bug #107044 for the paleolithic discussion
Comment 21 Ignacio Casal Quinteiro (nacho) 2014-09-17 06:27:45 UTC
for reference I agree with pbor:

currently in gca we return a IndentLevel value and let the caller to create the string out of it and delete and insert that level.

See the interface:
https://git.gnome.org/browse/gedit-code-assistance/tree/src/gca-indent-backend.vala

Basically the indent backend just implements the 2 methods:
get_triggers: which should be added to the lang files
get_indent: which is the one that returns the indent level (indent + alignment)

Apart from this, each indent backend provides a ini file with pointing out the languages that it supports. This would also be implemented in the lang file if this ever gets into gsv.
Comment 22 Ignacio Casal Quinteiro (nacho) 2014-09-17 06:30:02 UTC
(In reply to comment #18)
> One of the other things it would be nice to do is to recompute the indent after
> trigger characters. For example:
> 
>   if (foo)
>     {
>       item1();
>       item2();
>       }
> 
>       ^ this should trigger recomputation and unindent 2.

See the gca stuff, it deals with this case. Basically we provide a set of triggers which recompute the indentation.

Another topic to take into account which gca does not deal with yet is the indentation styles. For this I have some ideas but that can be discussed later on if we ever get this in gsv.
Comment 23 Sébastien Wilmet 2016-08-07 14:50:40 UTC
*** Bug 107044 has been marked as a duplicate of this bug. ***
Comment 24 Christian Hergert 2020-11-13 23:35:59 UTC
Moved to https://gitlab.gnome.org/GNOME/gtksourceview/-/issues/166