eclipse-theia / theia

Eclipse Theia is a cloud & desktop IDE framework implemented in TypeScript.
http://theia-ide.org
Eclipse Public License 2.0
20.05k stars 2.5k forks source link

Support GNU-style indentation #303

Open simark opened 7 years ago

simark commented 7 years ago

When working on GNU projects (e.g. GDB), we have to use a particular indent style. I think that style is funky enough that when we are able to support this, we will be able to support pretty much anything. I don't know if Monaco is flexible enough out of the box to support that only through configuration, that will have to be investigated.

Each indentation level is two spaces, so when you press tab or shift-tab, it should increase or reduce the indentation of by two spaces. However, when you reach 8 consecutive spaces, that should be replaced by a tab.

Here's an example of properly indented code:

VEC(breakpoint_p) *
static_tracepoints_here (CORE_ADDR addr)
{
  struct breakpoint *b;
  VEC(breakpoint_p) *found = 0;
  struct bp_location *loc;

  ALL_BREAKPOINTS (b)
    if (b->type == bp_static_tracepoint)
      {
    for (loc = b->loc; loc; loc = loc->next)
      if (loc->address == addr)
        VEC_safe_push (breakpoint_p, found, b);
      }

  return found;
}

Here's the same code with spaces replaced with <s> and tabs with <t>

VEC(breakpoint_p) *
static_tracepoints_here (CORE_ADDR addr)
{
<s><s>struct breakpoint *b;
<s><s>VEC(breakpoint_p) *found = 0;
<s><s>struct bp_location *loc;

<s><s>ALL_BREAKPOINTS (b)
<s><s>if (b->type == bp_static_tracepoint)
<s><s><s><s><s><s>{
<t>for (loc = b->loc; loc; loc = loc->next)
<t><s><s>if (loc->address == addr)
<t><s><s><s><s>VEC_safe_push (breakpoint_p, found, b);
<s><s><s><s><s><s>}

<s><s>return found;
}

To be clear, this issue is not about the editor being smart about where to place brackets or auto-ident (although that would be nice in the future), but just being able to specify what whitespaces are inserted when pressing tab.

simark commented 7 years ago

That would require have more preferences than "tabSize". In vim, for example, you have these:

set tabstop=8 : Width of a tab character when displayed (or more precisely, the multiple of columns to which the tab characters will span to)
set shiftwidth=2 : When you press `>>` or `<<` in Vim, of how many columns should it move left of right, I am not sure we would have an equivalent in Theia.
set softtabstop=2 : When you press the tab key, of how many columns should it move right
set noexpandtab : When you have one full tabstop worth of space, replace that with a tab.  "set expandtab" would mean the opposite, expand tab characters with the equivalent amount of spaces.

This is my interpretation, you can find the real doc by doing :help tabstop for example.

So at the very least, we will need a setting for:

  1. How many columns a tab character accounts visually.
  2. When pressing the tab key, how many columns do you want to move right.
  3. Should tabs be replaced with the equivalent in spaces (according to #1 I suppose). That would trigger only when doing an indentation action like pressing tab. If I type 8 spaces in a row, I don't think it should be replaced by a tab.
hexa00 commented 7 years ago

Note I tried to use that indent in VSCode and Atom and they both do not support it at all. Nor is there any extensions that do :(

So I'm pretty sure monaco doesn't.

I think the best thing would be to support auto indentation based on indent. (indent supports pretty much any indentation style). That way we could define the indentation in indent terms.

That would be for C/C++ only however, so providing a hook for auto indent based on the language would help.

So that clang-format could be used too for example. Or a language server.

IMO TAB should default to autoindent the line too rather than placing whatever character. Or have an easy option to make it so.

simark commented 7 years ago

The behavior of the tab key could be configurable, but I think we should always have a basic mode where tab just indents manually. We won't always know the language being edited and know how to indent it, so we need to have a solid way for the user to do whatever they want. After that, we can get more fancy for some languages we want to have better support for.

simark commented 7 years ago

Should we file an issue with the monaco project to show that there is interest in supporting this kind of behavior?

hexa00 commented 7 years ago

I'm not sure this should go into the editor directly ? If you know the number of tabs or the number of spaces you can know the indent level of a line in an extension then rewrite a number of spaces to tabs etc... I've seen some extensions do things like that.

MarkZ3 commented 7 years ago

formatting is part of the LSP and is already in Clangd although I don't think its possible to configure it well. It might be better to experiment with clang-format and document what's missing there.

hexa00 commented 7 years ago

IIRC clang-format supports the gnu indent style, but not the actual formatting of GDB code.

I wonder if it could do indent only

simark commented 7 years ago

The current issue is not related to any language support. It should be possible to set some preferences such that if the user creates a new .txt file and presses tab a few times, Theia follows the rules outlined above. So let's say you pressed tab a few times in an empty plain text file, it would successively contain this:

Press tab once:

<space><space>

and again:

<space><space><space><space>

and again:

<space><space><space><space><space><space>

and again:

<tab>

I suppose it will be possible for some language support to override this if the language dictates a standard, but it should still be possible to set the preferences to alter the basic indentation behavior of all files.