Emacs can slow down when opening files with exceptionally long lines, such as minified JavaScript or CSS, SQL dumps, or large JSON files. Emacs struggles with these files because it parses bi-directional text properties and applies complex regular expressions for syntax highlighting across thousands of characters on a single line.
One solution to prevent these files from slowing down Emacs is to use the built-in global-so-long-mode (or so-long-mode). When such files are visited, this mode detects abnormally long lines and automatically disables expensive features.
Below is a configuration to improve how global-so-long-mode handles these files, balancing performance and usability.
Managing syntax highlighting
By default, so-long disables font-lock-mode entirely to maximize performance. The configuration below retains syntax highlighting but limits the decoration level:
(with-eval-after-load 'so-long
;; Keep syntax highlighting
(setq so-long-minor-modes (delq 'font-lock-mode so-long-minor-modes))
;; Limit font-lock to the minimum decoration level to save CPU cycles
(add-to-list 'so-long-variable-overrides '(font-lock-maximum-decoration . 1)))
The benefit is that you maintain basic syntax highlighting, which makes code easier to read than plain text. The tradeoff is that even minimal font-lock parsing consumes CPU cycles, which can still cause minor performance degradation in massive files.
Changing the default action
By default, when so-long detects a file with abnormally long lines, its standard behavior is to replace the buffer's major mode with so-long-mode. This is undesirable if you want to edit files using their original major mode, which allows you to retain useful minor-mode behavior and tooling.
Setting so-long-action to so-long-minor-mode retains the original major mode while applying the configured so-long performance mitigations:
(setq so-long-action 'so-long-minor-mode)
Note: The trade-off is that so-long-minor-mode leaves some features active that so-long-mode would otherwise disable. If additional performance-heavy features cause latency, you must disable them explicitly by appending them to so-long-minor-modes (see below).
Extending target modes
By default, so-long primarily targets prog-mode, css-mode, sgml-mode, nxml-mode, and fundamental-mode, leaving other buffers unprotected.
Adding conf-mode and text-mode to so-long-target-modes extends this protection to structured configurations, documentation, and patch files:
;; Apply so-long to configuration, plain text files, and diff files
(with-eval-after-load 'so-long
(add-to-list 'so-long-target-modes 'text-mode)
(add-to-list 'so-long-target-modes 'conf-mode))
In practice, generated configuration files (such as dense JSON or exported INI data), single-line log dumps treated as text, and massive diffs regularly contain long lines that can freeze the Emacs.
Including these modes ensures that visiting non-code or patch buffers will not introduce UI freezes or responsiveness issues.
Managing variable overrides and display behavior
When so-long triggers, it overrides buffer-local variables to improve performance. However, some default settings degrade usability by marking buffers as read-only and allowing save-place-mode to reposition the point within long lines.
The snippet below adjusts so-long-variable-overrides to keep the buffer writable and disables save-place-alist, preventing unnecessary cursor calculations on long lines:
(with-eval-after-load 'so-long
;; Prevent so-long from attempting to restore the cursor position
(add-to-list 'so-long-variable-overrides '(save-place-alist . nil))
;; Ensure the buffer remains writable when so-long triggers, overriding the
;; default behavior that locks the buffer as read-only.
(setf (alist-get 'buffer-read-only so-long-variable-overrides nil t) nil))
Keeping basic UI elements
The default so-long-minor-modes includes display-line-numbers-mode. The following configuration removes it so it remains active when so-long triggers:
(with-eval-after-load 'so-long
;; Retain line numbers
(setq so-long-minor-modes (delq 'display-line-numbers-mode so-long-minor-modes)))
Disabling resource-intensive minor modes
Many third-party packages can become expensive on buffers containing very long lines. This block adds commonly used minor modes to so-long-minor-modes. When so-long triggers, active modes in this list are disabled for the current buffer.
(with-eval-after-load 'so-long
(dolist (mode '(;; Structural Editing and Parenthesis Matching
paredit-mode
enhanced-evil-paredit-mode
rainbow-delimiters-mode
smartparens-mode
smartparens-strict-mode
;; Regex and Custom Highlighting
easy-escape-minor-mode
highlight-defined-mode
highlight-indent-guides-mode
auto-composition-mode
;; Outline Scanning / Text folding
outline-minor-mode
treesit-fold-mode
ts-fold-mode
ts-fold-indicators-mode
;; State & History Persistence / I/O
undo-fu-session-mode
undo-tree-mode
better-jumper-local-mode
auto-revert-mode
;; Formatters & Whitespace Managers
aggressive-indent-mode
stripspace-local-mode
ws-butler-mode
;; Linters & Language Servers
eglot--managed-mode
eldoc-mode
flycheck-mode
flymake-mode
;; Spell Checkers
jinx-mode
spell-fu-mode
;; UI Overlays & Margins
indent-bars-mode
highlight-numbers-mode
diff-hl-mode
git-gutter-mode
line-reminder-mode
page-break-lines-mode
hl-fill-column-mode))
(add-to-list 'so-long-minor-modes mode)))
Adjusting the threshold
You can control when so-long activates by adjusting the following threshold:
;; so-long activates when a file contains a line exceeding the character count below
(setq so-long-threshold 6000)
Enable the mode globally
Finally, enable global-so-long-mode by adding the following to your Emacs configuration:
(global-so-long-mode 1)