Feature request: Line number 1 in front of first line of text
Is your feature request related to a problem? Please describe. With line numbers enabled, line number 1 is currently shown at the top of the buffer. This is perfectly workable but it would be nice if it was in front of the actual first line of text.
Describe the solution you'd like Have line number 1 be in front of the first line of text.

Thanks for submitting this request. Unfortunately it looks like making this happen would require modifying the Emacs C source code, which isn't something that could be covered in a patch to the topspace package elisp code. Based on this, I may need to close this issue without providing a solution, sorry about that!
More details: The line numbers are displayed by setting the display-line-numbers variable, which interfaces with the Emacs C source code. There is an elisp-based minor mode called display-line-numbers-mode, but it just modifies the display-line-numbers* variables which are interpreted in the C code.
Thanks for looking into it :)
I'm going to re-open this issue because it would be nice to have it implemented eventually as a longer-term issue, either by myself or someone else willing to help. It will likely require additional functionality to be added to the Emacs C core and then could be available in a future Emacs version. I will eventually either open an issue with the Emacs devel mailing list for this or try to contribute the change myself but I will have to wait till I have more time to spend understanding the Emacs C core first which I've only briefly looked at before.
@trevorpogue a hacky workaround for this issue in my case has been to use (run-with-idle-timer 0 nil #'sit-for 0), which causes Emacs to schedule an immediate redisplay and correct the problem. This needs to be called whenever the first line is moved to, or moved from.
(let ((ln-pos (line-number-at-pos)))
(if (eq ln-pos 1)
(run-with-idle-timer 0 nil #'sit-for 0)))
in my case, I have a lot of custom keybindings for buffer navigation with functions that constantly call (recenter) (among other commands) to keep my cursor squarely in the center of my screen at all times, so this pretty much solves the issue for me.
I've tried to find some sort of universal way of calling this, like using:
(defadvice linum-update (after fix-topspace-linum-update activate)
...)
(ad-activate 'linum-update)
but even though it executes accordingly, it doesn't seem to work at all. Even adding a ton of delay to run-with-idle-timer doesn't work, which is awfully confusing when I have it working fine elsewhere in interactive functions.
just some food for thought if anyone is interested in exploring further.
Thanks for the tip! And I also use many hooks calling recenter frequently and have my own custom cursor-centering minor mode that has some improvements over centered-cursor-mode (maybe I will put it on GitHub at some point).
Anyways, I tried your code snippet, calling (run-with-idle-timer 0 nil #'sit-for 0), but I didn't see any effect, the "1" was still displayed too high up in the left margin afterwards like in rappie's screenshot above. What exactly do you see happening for you?
@trevorpogue I was getting 1 displayed at the start of the file, but only immediately after jumping to or from the first line. Various actions would update the line number position, getting it to re-draw correctly. I just added some code to force emacs to redraw immediately instead.
This may have something to do with the fact I also change the face of the line numbers when highlighted, to complement hl-line. Here's my full configuration for it:
(require 'hl-line)
(defface custom-linum-hl
`((t :inherit linum :background ,(face-background 'hl-line nil t)))
"Face for the current line number."
:group 'linum)
(defvar custom-linum-format-string "%3d ")
(add-hook 'linum-before-numbering-hook 'custom-linum-get-format-string)
(defun custom-linum-get-format-string ()
(let* ((width (1+ (length (number-to-string
(count-lines (point-min) (point-max))))))
(format (concat "%" (number-to-string width) "d ")))
(setq custom-linum-format-string format)))
(defvar custom-linum-current-line-number 0)
(setq linum-format 'custom-linum-format)
(defun custom-linum-format (line-number)
(propertize (format custom-linum-format-string line-number) 'face
(if (eq line-number custom-linum-current-line-number)
'custom-linum-hl
'linum)))
(defadvice linum-update (around custom-linum-update)
(let ((custom-linum-current-line-number (line-number-at-pos)))
ad-do-it))
(ad-activate 'linum-update)
example of one of my binds (I am using sit-for directly here due to the preceding interactive calls, but scheduling it with run-with-idle-timer works regardless of where I call it in the function):
(defun custom-up-bind()
(interactive)
(call-interactively 'previous-line)
(call-interactively 'recenter)
(call-interactively 'move-end-of-line)
(let ((ln-pos (line-number-at-pos)))
(if (eq ln-pos 1)
(sit-for 0))))
image:

with my configuration, I can now only reproduce the line numbering bug with specific mouse actions.
perhaps the real solution might be changing/updating the face?
This is encouraging because I didn't actually think it was possible to ever have the 1 show below the very top of the window using elisp. I have yet to get it to do this on my end still but I will keep looking into it next week.
@trevorpogue to clarify, this is with linum-mode. If I run both modes at the same time I get the original bug only with display-line-numbers-mode:

my configuration predates display-line-numbers-mode, which is why I encountered this bug differently. Perhaps the workaround here is to use linum-mode with an improved hack for redrawing.
@jarcode-foss okay that makes more sense and is good to know. I was able to reproduce your bug now and I seem to have a fix for it. There is a function topspace--after-scroll that's called when no top space is present before scrolling but it is present after scrolling, and at the end of this function I made it call linum-update-window. If you like, you could try the most recent topspace version (from melpa or by cloning this repo) and let me know if it fixed your bug.
So, anyone who wants this feature can use linum-mode for now instead of the native display-line-numbers-mode (which is supposed to be faster than linum-mode). Edit: Thanks to @jarcode-foss for pointing this out.
For display-line-numbers-mode there seems to be another although very hacky solution. You can use the overlay property display-line-numbers-disable to stop the line numbering from being drawn. Then you can manually insert it with another overlay.
It's not perfect and quite ugly, but works surprisingly well.
My Conf:
;; Zen mode
(defun zen-mode-bodge ()
(let ((ov (make-overlay 1 1 nil t t)))
(overlay-put ov 'priority 9999999)
(overlay-put ov 'before-string (propertize " 1 " 'face 'line-number))
(overlay-put ov 'zen--remove-from-buffer-tag t))
(let ((ov (make-overlay 1 2)))
(overlay-put ov 'display-line-numbers-disable t)
(overlay-put ov 'zen--remove-from-buffer-tag t)))
(defun zen-mode-clear ()
(remove-overlays 1 2 'zen--remove-from-buffer-tag t))
;; install hooks
(advice-add 'topspace--enable :after #'zen-mode-bodge)
(advice-add 'topspace--disable :after #'zen-mode-clear)
There don't seem to be any hooks defined so I am using add-advice instead.