zed icon indicating copy to clipboard operation
zed copied to clipboard

Auto indentation is not working properly in C files

Open lungarella-raffaele opened this issue 7 months ago • 1 comments

Summary

When pressing "Enter" inside brackets the indentation is not quite right.

Steps to reproduce:

When writing code in C:

  1. write an "if" statement;
  2. open "{}" brackets and press enter inside them;
  3. the cursor is not in the proper indentation;
  4. then press "tab" and accept an autocomplete suggestino;
  5. the cursor moves to the previous position instead of keeping indentation;

Expected Behavior:

https://github.com/user-attachments/assets/39c59f9d-7a3f-437d-b6cb-cdd6962d420e

Actual Behavior:

https://github.com/user-attachments/assets/6bf3db8b-3183-4d2b-9724-51a346a7f11b

Follow up

This is more footage of how it's working. I am jumping around in files and pieces of code and I can't quite understand why it works in certain conditions. I am using the default settings. I hope it's clear when there is auto-indent and when there isn't

https://github.com/user-attachments/assets/c5601d7a-a4af-4758-9e0c-93b65395f620

Zed Version and System Specs

Zed: v0.186.9 (Zed) OS: macOS 15.4.1 Memory: 32 GiB Architecture: aarch64

lungarella-raffaele avatar May 15 '25 17:05 lungarella-raffaele

I also noticed weird auto indentation for C code - it seems it is related to format settings which place open brace { at the end of the line, which makes next line being indent far to the right when paste something. However, since VS code also behaves this way I suspect it may be coming from the language server.

I guess that logic shall be that position of open brace for C code shall not matter at all, and auto indentation shall just add configured indent spaces to the next line.

vsukhoml avatar May 16 '25 17:05 vsukhoml

However, since VS code also behaves this way I suspect it may be coming from the language server.

The expected behavior video is taken from vscode 🤔

lungarella-raffaele avatar May 17 '25 15:05 lungarella-raffaele

Using the latest, I wasn't able to reproduce this with a very minimal setup (shown in video). I'm also running on OSX - are there some format-on-save / linters running in your project?

https://github.com/user-attachments/assets/49fe1f83-564c-4548-a05e-57302b6ec0b8

Zertsov avatar Sep 07 '25 22:09 Zertsov

Trying on a simple file like yours it seems everything is right. But when trying it on a more complex file the indendation is often wrong. Here is an example project. The same of the original post.

Using:

	"tab_size": 4,
	"hard_tabs": true,

https://github.com/user-attachments/assets/a73f0436-4161-4c14-9360-59544a8f3be9

lungarella-raffaele avatar Sep 08 '25 12:09 lungarella-raffaele

Awesome, just cloned it and I'm seeing the same thing. I'll look into it for a bit today and see if I can find something.

Zertsov avatar Sep 08 '25 21:09 Zertsov

Been messing with this for a minute and I think I have a root cause. From the repo it looks like hard tabs weren't used, based on this output (or lack thereof)

voz in ~/git/shell branch: master [  ]
→ grep -P '\t' src/main.c | head

and after tons of logging, it looks like when you set that setting, Zed doesn't convert the file. Instead it tries to figure out where to put the indentation as if the file was written with whatever setting you have enabled (in this case, hard tabs of size 4). I took your repo and converted main.c to have hard tabs

voz in ~/git/shell branch: master [ unstaged ]
→ grep -P '\t' src/main.c
14:	setbuf(stdout, NULL);
15:	printf("$ ");
16:	fgets(input, 100, stdin);
17:	input[strlen(input) - 1] = '\0';
21:	pid_t ext_pid;
22:	int status, timeout;
24:	if (0 == (ext_pid = fork())) {
25:		if (-1 == (execve(bin, argv, NULL))) {
26:		  perror("External command failed");
27:		  exit(EXIT_FAILURE);
28:		}
29:	} else if (ext_pid > 0) {
30:		waitpid(ext_pid, &status, 0);
31:	} else {
32:		perror("Fork failed");
33:		return -1;
34:	}
36:	return 0;
40:	char input[100];
41:	char *tokens[MAX_TOKENS];
43:	int token_count;
44:	while (1) {
45:		token_count = 0;
47:		user_input(input);
49:		parse_tokens(input, tokens, &token_count);
51:		if (strcmp(tokens[0], "exit") == 0) {
52:			break;
53:		} else if (is_builtin(tokens[0]) == 0) {
54:			run_builtin(tokens[0], &tokens[1]);
55:		} else {
56:			char *exec = is_in_path(tokens[0]);
57:			if (exec != NULL) {
58:				int status = run_external(exec, tokens);
59:				if (status == -1) {
60:					printf("Error while executing: %s\n", exec);
61:				}
62:			} else {
63:				not_found(tokens[0]);
64:			}
65:		}
66:	}
68:	return 0;

and after that, I found that the issue goes away. I attached a video showing what it looks like after the file is converted to hard tabs, and what it looks like in a file that isn't using hard tabs. Are you able to reproduce this behavior on your end?

https://github.com/user-attachments/assets/4f0feea0-2263-4b66-9cac-6f3c2b565d73

Zertsov avatar Sep 09 '25 00:09 Zertsov

Yess, using hard tabs everything works fine (even with different tab sizes). I have noticed that having the default formatter for the C language it changes the indentation from tabs to spaces. It wasn't a thing I was really considering, I always assumed that the visualization of the file would use the settings of Zed, so that was another layer of confusion. To fix this I added a .clang-format file and changed the indentation rules.

Thanks so much for covering this issue! :)

lungarella-raffaele avatar Sep 09 '25 07:09 lungarella-raffaele

No problem! I was looking around for issues to fix and thought this would be a fun one :D

For what it's worth, I think this could be related to this issue - I'm seeing a few things like this, so you're not alone!

Zertsov avatar Sep 09 '25 16:09 Zertsov

Conclusions

I encountered the same problem with Rust. rustfmt uses spaces, and the indentation wasn’t right. Switching to hard_tabs in rustfmt.toml solved the auto-indent issue.

Then I tried switching my settings around, and I think I found where the problem lies. The issue was Zed’s configuration conflicting with the file’s indentation. Since the formatter always changed the file to use spaces, it kept colliding with my editor settings. In fact, when I changed Zed’s settings to use spaces, everything worked fine.

Right now, I’ve removed the "hard-tabs: true" configuration and will rely on the formatter for indentation.

Closing due to skill-issue 😆

lungarella-raffaele avatar Sep 10 '25 07:09 lungarella-raffaele