SoLong

This is a workaround for the issue of large ‘minified’1 files of programming code (i.e., code that has been compacted into the smallest file size possible, which often entails removing newlines should they not be strictly necessary) bringing Emacs to its knees on account of the relevant modes not being (remotely) optimised for that use-case.

When the lines in a buffer are so long that performance could suffer to an unacceptable degree, we say “so long”2 to the buffer’s major mode, and invoke something much more basic in its place (including disabling minor modes which are considered to affect performance noticeably).

See the commentary in so-long.el for more details.

1 for example, https://code.jquery.com/jquery-git.min.js
2 farewell, auf wiedersehen, etc…

Download and Install

Emacs 27+

Included as standard. Simply enable in your init file with:

 (global-so-long-mode 1)

Emacs versions < 27 (minimum 24.4)

Install using one of the options below, and then enable in your init file with:

 (when (require 'so-long nil :noerror)
   (global-so-long-mode 1))

GNU ELPA

Install the so-long package from the default GNU ELPA repository:

 M-x package-install RET so-long RET

Use-package & Quelpa

  (use-package so-long
    :quelpa (so-long :url "https://raw.githubusercontent.com/emacs-mirror/emacs/master/lisp/so-long.el" :fetcher url)
    :config (global-so-long-mode 1))

Manual installation

Alternatively, the latest version of so-long.el is also available from its Savannah repository (n.b. the code is no longer maintained here at the EmacsWiki).

You must either place the library somewhere in your Emacs load-path, or use M-x package-install-file for the downloaded file.

Documentation

Extensive documentation is included in the library itself; use M-x so-long-commentary to read it in OutlineMode inside Emacs. This documentation is also displayed (more plainly) at https://elpa.gnu.org/packages/so-long.html or if you view so-long.el itself.

Configure

See M-x so-long-commentary for details of controlling the situations in which so-long-mode will be triggered, and the actions that it takes.

M-x customize-group RET so-long RET to configure the library.

Minor modes

Numerous minor modes are disabled by default (if they were enabled in the first place; including when the buffer-local mode is enabled by a globalized minor mode). These include the likes of:

It is a good idea to customize so-long-minor-modes to add any additional buffer-local minor modes that you use which you know to have performance implications. Please report any examples you encounter upstream with M-x report-emacs-bug (regardless of whether the mode is part of Emacs, or from a third party library or package), so that

Variable Overrides

Several variables are also set buffer-locally to improve performance when long lines are detected. Again, refer to M-x so-long-commentary for all of the details.

Hooks

While the standard mode hook ‘so-long-mode-hook’ (which runs between ‘change-major-mode-after-body-hook’ and ‘after-change-major-mode-hook’) is available, ‘so-long-hook’ is generally the best place to put custom code, because it runs after globalized minor modes have acted (immediately after the minor modes above have been disabled, to be specific).

 (add-hook 'so-long-hook 'my-so-long-hook)
 (defun my-so-long-hook ()
   "Used in `so-long-hook'."
   ;; Disable the old `idle-highlight' (pre-`idle-highlight-mode')
   (when (bound-and-true-p idle-highlight-timer)
     (cancel-timer idle-highlight-timer)
     (setq idle-highlight-timer nil)))

Troubleshooting

Any elisp library has the potential to cause performance problems, and while so-long addresses some important common cases, it’s entirely possible that your own config contains problem cases that are unknown to this library.

If a file is still taking a very long time to load with so-long enabled, you should test the following command:

 emacs -Q -l /path/to/so-long.el -f so-long-enable <file>

If the file loads quickly when that command is used, you’ll know that there is something in your personal configuration which is causing problems. If this turns out to be a buffer-local minor mode, or a user option, you can hopefully alleviate the issue by customizing ‘so-long-minor-modes’ or ‘so-long-variable-overrides’ accordingly.