Odd Behavior with Carriage Return (CR)
Emacs handles files with different end-of-line (EOL) conventions well, but when using .editorconfig, it exhibits strange behavior. For example, in VSCode, when .editorconfig is configured with end_of_line = lf and you open a file with CRLF line endings, the file opens normally without any Carriage Return characters appearing. After saving, the file is automatically converted to LF line endings as per the .editorconfig settings.
However, in Emacs, when end_of_line is set to lf in .editorconfig and you open a file with CRLF line endings, the Carriage Return (^M) characters immediately appear. This behavior is unexpected, as without .editorconfig, Emacs correctly handles the conversion of CRLF to LF without any issues. It seems that the conversion forced by .editorconfig causes the escaped Carriage Return symbols to appear.
(I'm using UTF-8 because it's my usual encoding. However, since the issue is related to CRLF line endings, it should be reproducible with any character encoding.)
I expect the behavior to be similar to other text editors, where the file opens with its original EOL and is only converted when saved. With this behavior, Emacs opens the file in dos mode, so the CR characters do not escape. If I make changes and save the file, it gets fully converted to LF, and Emacs then displays it in unix mode. I’m not sure if this behavior can be changed with a setting, as I’ve tried to find one but haven’t had any luck.
Steps to Reproduce:
- Create a folder with a .editorconfig file containing the following configuration:
root = true
[*]
end_of_line = lf
- Create a text file encoded in UTF-8 with CRLF line endings.
- Open the file in Emacs (tested on Emacs 30.1 with MSYS64 on Windows).
- The file opens and immediately displays the ^M Carriage Return characters.
The image shows the result of the reproducible steps. Emacs is configured with a clean setup, with the only content in the init.el being (editorconfig-mode 1).
As an Emacs user, I'd consider it a bug if opening a file, adding one char somewhere, and saving the file ends up modifying every single line in the file (by removing CRs characters, or converting CRs to LFs, ...). So, from where I stand, the behavior of those "other text editors" is a bug that they should fix.
The EditorConfig spec doesn't say much about how it's intended to be used:
Set to
lf,cr, orcrlfto control how line breaks are represented. The values are case-insensitive.
Other than VSCode and Emacs, which editors did you try it with? Did you try with a file using a mix of CRLFs and LFs? How about a mix of CRs and LFs?
Also: how come your file contains CRLFs if you specified lf in .editorconfig?
IMO, integration of EditorConfig support into Emacs should be done in a way that's "natural" for Emacs users, i.e. it should behave as much as possible in the same way as if the corresponding configuration was made in the most natural way via .emacs, or .dir-locals.el, or somesuch.
The closest I know to .editorconfigs end_of_line would be to set file-coding-system-alist and such settings behave like Emacs's current support of EditorConfig rather than like VSCode's, tho it does offer the choice to specify separately what happens when reading and when writing, so you can also make it behave like you want with a tiny bit more work. So it's weak endorsement of the current behavior.
As an Emacs user, I'd consider it a bug if opening a file, adding one char somewhere, and saving the file ends up modifying every single line in the file (by removing CRs characters, or converting CRs to LFs, ...).
I also use Emacs and i don't consider it a bug, because it is explicitly declared by the user in the .editorconfig, so this isn’t an “I didn’t expect this” moment.
Other than VSCode and Emacs, which editors did you try it with?
I tried in Neovim (0.11.4), PyCharm (2025.2.1), Sublime Text (4200).
Did you try with a file using a mix of CRLFs and LFs? How about a mix of CRs and LFs?
In a mixed CRLF and LF file, Emacs shows the CR symbol, which in my opinion is a great way to handle mixed files.
PyCharm, Sublime Text, and VSCode create a newline below (for some reason) on the CRLF lines, which is a horrible way to handle this.
In a mixed CR and LF file, Emacs displays the file as (Mac), and everything is fine. All CR and LF lines are displayed normally without any escaped symbols. The same happens with the other editors (PyCharm, VSCode, Sublime Text), except for Neovim, which shows everything in a single line with ^M separating what is supposed to be a new line.
IMO, integration of EditorConfig support into Emacs should be done in a way that's "natural" for Emacs users, i.e. it should behave as much as possible in the same way as if the corresponding configuration was made in the most natural way via .emacs, or .dir-locals.el, or somesuch.
In a fresh Emacs setup, if the only added line to the config file is (setq coding-system-for-write 'utf-8-unix), it will behave as expected. With this option, if a CRLF file is opened, Emacs will display it in dos mode, but when the user saves it, Emacs will convert the file to LF and automatically change the display to unix mode (as seen in the modeline). This happens flawlessly without showing any ^M.
The closest I know to .editorconfigs end_of_line would be to set file-coding-system-alist and such settings behave like Emacs's current support of EditorConfig rather than like VSCode's, tho it does offer the choice to specify separately what happens when reading and when writing, so you can also make it behave like you want with a tiny bit more work. So it's weak endorsement of the current behavior.
Using file-coding-system-alist in this situation for every file would be an impractical hack, since coding-system-for-write is the expected and practical behavior, as it handles all cases without further changes.
To be more specific, the problem here is not the conversion of the file. The problem is that EditorConfig enforces Emacs to display the file according to the end_of_line setting (for example, in LF mode), even when the file is in CRLF. Because of this, Emacs correctly shows carriage return symbols, since it is being enforced to display in LF mode on a file with CRLF endings. But as a result, it escapes the CR symbols and interferes with the built-in conversion. The user doesn’t gain anything from EditorConfig forcing Emacs to display the file with the end_of_line value. It doesn’t convert the file, doesn’t improve the display since it clutters the file with ^M, and doesn’t help the user convert the file manually, as these escaped characters interfere with the conversion.
The behavior I am trying to achieve is the same as described above with the coding-system-for-write setting, but using EditorConfig. This could be achieved if EditorConfig did not enforce Emacs to change the display mode to match the end_of_line value, and instead let Emacs handle the file display, while enforcing the conversion on save, letting Emacs automatically update the display mode to the file's new EOL as specified by the user in .editorconfig.
The image above shows a file with mixed CR and LF lines outside of .editorconfig. Emacs handles the display correctly.
The same file, but inside a .editorconfig folder with the same configurations described previously (end_of_line = lf).
If i open the same file without editorconfig using the setting coding-system-for-write inside Emacs config, it will open normally like first image, and after save it will convert the file to LF and change the display to unix without any issues.
I presume that the Emacs user, the person who wrote the file, and the person who wrote the .editorconfig file are three distinct persons, so the Emacs user can definitely be surprised. And in general Emacs makes efforts to try and make sure that the bytes of a file are preserved in the parts of the file that were not modified. So maybe you wouldn't be surprised, but others would.
Setting coding-system-for-write would have significant undesirable side effects (the docstring tries to warn users about it: it's meant to be let-bound around specific chunks of code), so it's not a good comparison.
I wasn't thinking of setting file-coding-system-alist for all files but to use the regexp part to match filenames in specific directories. It's not nearly as convenient as .dir-locals.el or .editorconfig but I couldn't find anything closer.
But yes, your suggestion reminded me of an alternative: use a find-file-hook that tests buffer-file-name to see if it's within some specific directories and then changes buffer-file-coding-system. That would behave more like you'd want.
If we really want such a behavior, Emacs should warn (or prompt the user) when that does change the file's EOL convention.
I get the point that Emacs is an editor that tries to explain to the user what it is doing, and tries to never do anything unexpected or without warning the user first. But if EditorConfig enforces certain changes to files in every other supported editor, why not in Emacs?
I understand Emacs not wanting to change files without the user’s “knowledge,” but if the user enables EditorConfig mode globally and is working on a project that uses EditorConfig to ensure consistency, I don’t think Emacs should worry about changing the files, since this is an option the user deliberately enabled.
In the "What is EditorConfig?" section on the site:
EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
So what is the point of using EditorConfig in Emacs? If the user needs to configure multiple variables like let-bound coding-system-for-write chunks of code, or use file-coding-system-alist, find-file-hook, buffer-file-name, and so on? Isn’t EditorConfig supposed to be “easy”? Because if a user needs to configure so many things to bypass EditorConfig making Emacs behave differently from the default, I don’t see why use it.
Since this narrative of the "surprised user" is not going away.
Maybe a middle ground is better?
What about EditorConfig not forcing Emacs to read the file using the end_of_line value?
Instead, let EditorConfig enforce end_of_line only in new files created inside the project, while respecting already existing ones.
This way, the user needs to deliberately convert the file themselves, removing the element of surprise, since they are the one doing it. It would respect existing files and let Emacs handle the display, rather than forcing it to read the file with a different EOL. I can’t see what Emacs users gain from EditorConfig forcing Emacs to change the display mode, as shown in the two photos above.
I am not talking about conversion (let the file stay the same), just don’t force the display of the file with the wrong EOL. This doesn’t make any sense, because if Emacs already knows the file is, for example, CR or CRLF, why not let Emacs handle it? Why force Emacs to display the file in the wrong format?
Let the Emacs user develop the Lisp for automatically converting if that’s what they want, but do not force the display to change.
This is very frustrating when using multiple programs that generate files that need to be edited on systems like Windows (which uses CRLF) in a codebase that has LF files (such as when working with WSL).
Ah, so we're getting to the crux of the matter: how come you have files whose EOL encoding is inconsistent with what .editorconfig stipulates?
This should be a rare occurrence, which is why the exact behavior of the editor should be rather unimportant.
The problem is not why files have inconsistent EOL settings compared to what .editorconfig stipulates. The problem is that .editorconfig forces Emacs to display the file incorrectly, providing no benefits in doing so and behaving differently from essentially all other .editorconfig implementations.
This may be a rare occurrence on some GNU/Linux distros or on macOS, but it is NOT a rare occurrence on Windows. For example, some tools (like npm, cargo, etc.) generate files using LF, but when working with C++ code on Windows (e.g., using the Visual Studio Compiler Tools), the default is CRLF. It is very common to have a Windows project containing both LF and CRLF files (Git normalizes files to LF by default, so this is not an issue when pushing to GitHub). However, it is a problem when using Emacs (with .editorconfig; since Emacs without it handles correctly.) to develop projects on Windows.
Of course, you can configure the default VS compiler tools to generate LF, just as you can configure most development tools on Windows. But this does NOT change the fact that the .editorconfig behavior is incorrect.
Can you explain to me what is the benefit of .editorconfig forcing Emacs to READ/DISPLAY a CRLF file in a LF mode?
IIUC you "want to talk to my manager", so I'll let someone else chime in.
(I'm not the manager 😅 )
I understand the problem as that Emacs should display the EOL more consistently, while leaving the content of the file following what .editorconfig stipulates.
I don't know how we can achieve this in Emacs, @monnier is probably the most knowledgable person in this conversation. Based on my understanding, this can't be achieved without some dirty hacks, and likely causes side effects. Perhaps this is not so feasible unless Emacs provides some APIs?
I don't think it would be hard, actually.
It's basically a question of changing the code such that the EOL setting is not merged with the setting of the charset before reading the file. Instead, editorconfig--advice-find-auto-coding would only handle the charset setting, and then the EOL setting would be applied along with all the other settings (i.e. in editorconfig--advice-find-file-noselect) to modify buffer-file-coding-system.