Auto indentation is not working properly in C files
Summary
When pressing "Enter" inside brackets the indentation is not quite right.
Steps to reproduce:
When writing code in C:
- write an "if" statement;
- open "{}" brackets and press enter inside them;
- the cursor is not in the proper indentation;
- then press "tab" and accept an autocomplete suggestino;
- 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
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.
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 🤔
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
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
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.
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
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! :)
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!
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 😆