Emacs Asked by Jorgen Schäfer on February 3, 2021
As a programmer, I want to see a ruler at a specific column (usually 80), both so I see when I cross that column, but also to see how close I am getting to it so I can reformat my code early.
The options I have found so far are all not achieving this goal:
whitespace-mode
, column-enforce-mode
, and column-marker
only highlight individual rows after the text in the row has already passed the fill-column
. I’d like to see when I am getting close to the column, not just when I cross it.fill-column-indicator
would be a good solution, except it breaks auto-complete-mode
, company-mode
, avy
, and more. These are issues that seem hard to fix, each requiring an individual workaround — e.g., see the company-mode
issue and the auto-complete-mode
issue, the latter over two years old).Are there any better alternatives?
In Spacemacs this functionality is easily toggled using SPC t f
.
I'm not sure exactly how it is implemented but Spacemacs seems to use the fill-column-indicator
package (defined in the .emacs.d/layers/+source-control/git/packages.el
file).
Spacemacs also implements company and avy, I'm not sure if the fill-column-indicator
breaks anything there.
Anyway for ease of configuration it is worth to take a look at Spacemacs
Answered by dalanicolai on February 3, 2021
Are there any better alternatives?
Emacs 27 added support for a fill column indicator natively by way of the buffer-local minor mode display-fill-column-indicator-mode
and its global counterpart global-display-fill-column-indicator-mode
(see (info "(emacs) Minor Modes")
).
For example, you can enable it in most programming language modes by adding something like the following to your user-init-file
(see (info "(emacs) Hooks")
):
(add-hook 'prog-mode-hook #'display-fill-column-indicator-mode)
Here it is in action:
Quoth (info "(emacs) Displaying Boundaries")
:
14.15 Displaying Boundaries
===========================
Emacs can add an indicator to display a fill column position. The fill
column indicator is a useful functionality especially in ‘prog-mode’ to
indicate the position of a specific column.
You can set the buffer-local variables
‘display-fill-column-indicator’ and
‘display-fill-column-indicator-character’ to activate the indicator and
control how it looks, respectively.
Alternatively you can type ‘M-x display-fill-column-indicator-mode’
or ‘M-x global-display-fill-column-indicator-mode’ which enables the
indicator locally or globally, respectively, and also chooses the
character to use if none is already set. It is possible to use the
first one to activate the indicator in a hook and the second one to
enable it globally.
There are 2 buffer local variables and 1 face to customize this mode:
‘display-fill-column-indicator-column’
Specifies the column number where the indicator should be set. It
can take positive numerical values for the column or the special
value ‘t’ which means that the variable ‘fill-column’ will be used.
Any other value disables the indicator. The default value is ‘t’.
‘display-fill-column-indicator-character’
Specifies the character used for the indicator. This character can
be any valid character including Unicode ones if the font supports
them.
When the mode is enabled through the functions
‘display-fill-column-indicator-mode’ or
‘global-display-fill-column-indicator-mode’, the initialization
functions check if this variable is non-‘nil’, otherwise the
initialization tries to set it to ‘U+2502’ or ‘|’.
‘fill-column-indicator’
Specifies the face used to display the indicator. It inherits its
default values from the face ‘shadow’ but without background color.
To change the indicator color you need only set the foreground
color of this face.
Answered by Basil on February 3, 2021
Since fill-column-indicator
is quite heavy, this solution shows a character to the right of the current line.
So when you're typing you can see the line limit before you exceed it.
This defines the minor-mode hl-line-margin-mode
:
;; Global, ensures one active margin for the active buffer.
(defvar hl-line-margin--overlay nil)
(defun hl-line-margin--overlay-clear ()
"Clear the overlays."
(when hl-line-margin--overlay
(delete-overlay hl-line-margin--overlay)
(setq hl-line-margin--overlay nil)))
(defun hl-line-margin--overlay ()
"Create the line highlighting overlay."
;; Remove in the event of a changed buffer,
;; ensures we update for a modified fill-column.
(when (and hl-line-margin--overlay
(not (eq (current-buffer)
(overlay-buffer hl-line-margin--overlay))))
(hl-line-margin--overlay-clear))
(unless hl-line-margin--overlay
(setq hl-line-margin--overlay (make-overlay 0 0))
(let ((space `((space :align-to ,fill-column)
(space :width 0))))
(overlay-put hl-line-margin--overlay 'after-string
(concat (propertize " " 'display space 'cursor t)
(propertize " " 'face '(:inverse-video t))))))
(let ((eol (line-end-position)))
(unless (eql eol (overlay-start hl-line-margin--overlay))
(move-overlay hl-line-margin--overlay eol eol))))
(defun hl-line-margin-mode-enable ()
"Turn on `hl-line-margin-mode' for the current buffer."
(add-hook 'post-command-hook #'hl-line-margin--overlay nil t))
(defun hl-line-margin-mode-disable ()
"Turn off `hl-line-margin-mode' for the current buffer."
(hl-line-margin--overlay-clear)
(remove-hook 'post-command-hook #'hl-line-margin--overlay t))
;;;###autoload
(define-minor-mode hl-line-margin-mode
"Show a character at the fill column of the current line."
:lighter ""
(cond (hl-line-margin-mode
(jit-lock-unregister #'hl-line-margin-mode-enable)
(hl-line-margin-mode-enable))
(t
(jit-lock-unregister #'hl-line-margin-mode-disable)
(hl-line-margin-mode-disable))))
If you use evil-mode
and want to limit this to insert mode you can add the following hooks:
(add-hook 'evil-insert-state-entry-hook #'hl-line-margin-mode-enable)
(add-hook 'evil-insert-state-exit-hook #'hl-line-margin-mode-disable)
Answered by ideasman42 on February 3, 2021
After much suffering because of various bugs fill-column-indicator
introduces, I eliminated it from my config for good.
What I currently use is built-in Emacs functionality to highlight lines that are too long. This even looks better, I wouldn't enable fill-column-indicator
now even if it were bug-free.
For a start you may grab my setup:
(setq-default
whitespace-line-column 80
whitespace-style '(face lines-tail))
Then enable it where you want. I use it only in programming context:
(add-hook 'prog-mode-hook #'whitespace-mode)
Answered by Mark Karpov on February 3, 2021
Not exactually what you want, but ruler like @Malabarba♦ will waster space, here is better solution:
There is a built-in package in emacs-goodies-el
(recommend to install it in terminal) called highlight-beyond-fill-column.el, add this to your .emacs
or init.el
:
(setq-default fill-column 80)
(add-hook 'prog-mode-hook 'highlight-beyond-fill-column)
(custom-set-faces '(highlight-beyond-fill-column-face
((t (:foreground "red" )))))
The text beyond fill-column
which is 80 in the snippet will be highlighted with the color of red
. You can set the face as you like.
Answered by CodyChan on February 3, 2021
This EmacsWiki page has lots of information about different ways to mark a particular column or otherwise let you know when you go past it.
The one I use is Mode Line Position.
But others include showing a vertical line at the column (Column Marker, Fill-Column Indicator) and using whitespace mode to highlight text that goes past the column.
(If you need the line to be far to the right of all text in all rows, you can always turn on picture-mode
, but that is probably useful here only as a temporary workaround.)
See also Find Long Lines for ways to find long lines on demand.
Answered by Drew on February 3, 2021
fill-column-indicator
is the most mature solution, and if you find overlay-based code with which it conflicts, you can add code to suspend fci-mode
while the conflicting code is active. For example, the following code makes it work with auto-complete
:
(defun sanityinc/fci-enabled-p () (symbol-value 'fci-mode))
(defvar sanityinc/fci-mode-suppressed nil)
(make-variable-buffer-local 'sanityinc/fci-mode-suppressed)
(defadvice popup-create (before suppress-fci-mode activate)
"Suspend fci-mode while popups are visible"
(let ((fci-enabled (sanityinc/fci-enabled-p)))
(when fci-enabled
(setq sanityinc/fci-mode-suppressed fci-enabled)
(turn-off-fci-mode))))
(defadvice popup-delete (after restore-fci-mode activate)
"Restore fci-mode when all popups have closed"
(when (and sanityinc/fci-mode-suppressed
(null popup-instances))
(setq sanityinc/fci-mode-suppressed nil)
(turn-on-fci-mode)))
Answered by sanityinc on February 3, 2021
Here is one option which is more robust, it breaks almost nothing
(occasionally company-mode being a noteworthy exception), but is not as convenient
as fill-column-indicator
.
Use
header-line-format
to mark the 80th column on the header.
Something like the following should suffice:
(setq-default header-line-format
(list " " (make-string 79 ?-) "|"))
You should change the number of spaces in that first string depending on the size of your left fringe. But other than that, this should work reasonably well. It's not as convenient as a ruler in the actual buffer, but it helps.
You can also set it to apply only on programming buffers.
(defun prog-mode-header-line ()
"Setup the `header-line-format' on for buffers."
(setq header-line-format
(list " " (make-string 79 ?-) "|")))
(add-hook 'prog-mode-hook #'prog-mode-header-line)
Result:
You should get something like the following (the first line is not actually in the buffer, but in the header).
-------------------------------------------------------------------------------|
;; This is what your buffer should look like all the way up to column number 80.
(setq some-dummy-variable we-are-all-friends)
Answered by Malabarba on February 3, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP