Alexey-T / CudaText

Cross-platform text editor, written in Free Pascal
Mozilla Public License 2.0
2.4k stars 167 forks source link

Sub-optimal JavaScript caret indentation #5425

Closed pintassilgo closed 3 months ago

pintassilgo commented 3 months ago

As you may know, JavaScript supports if/else without blocks {} for single statements. For instance:

function a() {
  function test() {
    if (true)
      return;
  }
}

If I place the caret after return; and press Enter to make a new line, caret should align with if, so that I can for instance type else. This works fine in SublimeText. But Cuda aligns with return as if I would type a second statement within if, something that is not allowed in JS when if is declared without brackets.

Edit: other issue that I had written here was moved to #5427.

pintassilgo commented 3 months ago

One more thing: Sublime is smart to auto trim empty lines that were created with indentation. moved to https://github.com/Alexey-T/CudaText/issues/5426

Alexey-T commented 3 months ago

The second post deserves the separate issue... let us not combine all stuff into one issue.. it is hard to track then the solving

Alexey-T commented 3 months ago

for 1st post. I suggest to add option "c_like" (true/false). for lexer-specific configs. if True, then Cud can handle this issue: it will analize {} on last 2 lines, if/while in previous line, and do the unindent on pressing Enter in this case. maybe it will skip // commented lines too while analyzing.

not simple solution. so will do little later.

pintassilgo commented 3 months ago

OK, thanks. Reminder that there are two issues/suggestions in 1st post, you talked above about one of them, the other one is to allow jumping to indentation position on pressing Tab once when caret position is way to the left. For instance, if I move caret up to an empty line, then press Enter to create another new line then press Tab. Do you want me to create a separated issue for that one too?

Alexey-T commented 3 months ago

Better create the new issue for sub-issue 2.

Alexey-T commented 3 months ago

how does Sublime know that it needs 'special indentation' in this situation? is it some option, per-lexer? or hard-coded for fixed lexers (JS, C, C++, C#, what about others from packages)? it's interesting... can you ask them?

pintassilgo commented 3 months ago

It's by default, I didn't change Sublime options. Sublime is closed source, so I have no idea how it was implemented. Right now I cannot test (only later), but I believe VSCode also works as expected.

I can't say in terms of implementation and don't know about other languages, but regarding JS it's easy to know by just reading the code: when the first statement after if is not enclosed by {}, it's an implicit if block which ends when:

if (1)
  true; // inside the if
console.log(1); // outside the block
if (1)
  true, console.log(1); // inside
if (1)
  true // inside
console.log(1); // outside
if (1)
  true, // inside
  console.log(1); // inside
if (1)
  true // inside
  , // inside
  console.log(1); // inside
Alexey-T commented 3 months ago

I know what to do here. count lexer tokens from caret pos to the top. find token 'if' and token ';' and token '{'. it will be not simple code. also we need the option (per lexer) 'lexer is C like'. it will be rather complex change.. i don't like it..

pintassilgo commented 3 months ago

Unfortunately I can't help with with that, but I believe this is not an enhancement but a bug, because auto indentation while user types is wrong in current Cuda - and this issue doesn't exist with other popular editors (Sublime for sure, probably VSCode and some others too).

Alexey-T commented 3 months ago

BTW,

    if (true)
      return;

the same case can happen with while and for blocks? and some other blocks?

pintassilgo commented 3 months ago

Yes, while, do while and for. But not function, that doesn't work.

Alexey-T commented 3 months ago

Yes, and function id does not exist in C. and foreach for C#.

pintassilgo commented 3 months ago

and foreach for C#.

There's array.forEach() in JavaScript, but the argument is a function, so there's nothing to think about, Function without brackets is only allowed in arrow function, like () => true.

JS is super weird and complex for this type of work because it's very permissive, it even allows things like console.log,'cudatext' instead of the usual console.log('cudatext').

Alexey-T commented 3 months ago

array.forEach will be skipped becase comparing is case sensitive. all keywords to stop at

if
while
do
for
foreach
else
catch
switch
try
pintassilgo commented 3 months ago

There's no foreach in JS, only the case I said in previous message.

This issue affects if, else, while, do and for.

Alexey-T commented 3 months ago

adding first code for this issue. more to do for me, e.g. need to auto-detect C-like lexers by lexer rules. todo.

I added detection 'additional UNindent is needed' (what you asked for in the 1st post). did not add 'additional indent is needed' - that is handled already by option "indent_auto_rule" and handled auto when user types if (...) {|}

Alexey-T commented 3 months ago

Added. Test the beta pls, http://uvviewsoft.com/c/

pintassilgo commented 3 months ago

What I described in first comment is fixed, thanks, for all the 5 cases I said (if, else, while, do and for).

I don't understand indent_auto_rule option.

But I can say Cuda still doesn't indent when I press Enter when I don't open brackets.

function a() {
  function test() {
    if (true)|
  }
}

Pressing Enter. Expected:

function a() {
  function test() {
    if (true)
      |
  }
}

Actual results:

function a() {
  function test() {
    if (true)
    |
  }
}
Alexey-T commented 3 months ago

good. we have almost done it.

But I can say Cuda still doesn't indent when I press Enter when I don't open brackets.

yes. it is the work of the "indent_auto_rule" option as I said. cmt to the option says the work for C-langs is not needed, it is only when you type if (...){|}. but when you don't type paired brackets, work is needed. option "indent_auto_rule" value is needed. did you fill it (for JS in ur case)?

Alexey-T commented 3 months ago

in the option, pass the regex which finds the if (true). it may be

^\s*(if|for)\s*\(.*?\)

pintassilgo commented 3 months ago

Thanks. This works in a simple test:

"indent_auto_rule": "^\\s*(if|else|for|while|do)\\s*\\(.*?\\)",

I just believe all users expect this to work by default (as it is with other editors), let alone needing this complex value for a hard to understand option. As it stands, I believe users would need to specifically search for this bug in issues page, find this link and read your comment above. In real world this is currently the only viable way to fix the issue, no one could solve it by their own (for something that should work out of the box, without tweaking options).

Alexey-T commented 3 months ago

what is left to-fix from this issue?

pintassilgo commented 3 months ago

It's done, what was missing was fixed now in #5447.

Alexey-T commented 3 months ago

BTW. how do i detect c-like lexers:

hope it's OK.