Subject: hscroll current-line scrolls short lines too far to the left

From: Erik van Zwol <[email-masked]>
Date: Sun, 21 Aug 2022 22:03:29 -0600

starting from 'emacs -Q':
Toggle-truncate-lines (so that long lines are truncated)
Evaluate the following:
(setq auto-hscroll-mode 'current-line)
(setq hscroll-margin 5)
(setq hscroll-step 1)
Insert enough text such that the line starts to hscroll
On the line directly below, insert enough text to fill about half the
width of the frame
Move point to the long line near the end (must be hscrolling the single
line)
Move point down to the next line, it should hscroll even though it does
not need to
See the animated gifs on this post:
https://www.reddit.com/r/emacs/comments/wgef0b/looking_for_better_alternative_to_autohscrollmode/

I have attached a patch that I think fixes the issue.  Please tell me
how to proceed, and what other information you need.

In GNU Emacs 27.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.20)
 of 2021-11-22 built on erik-lair
Windowing system distributor 'The X.Org Foundation', version 11.0.12013000
System Description: Ubuntu 20.04.3 LTS

Recent messages:
Type C-c C-c to finish, C-c C-k to cancel, and M-p and M-n to recover older
messages
Auto-saving...done
Formats have changed, recompiling...done
fart
Updating buffer list...done
Commands: m, u, t, RET, g, k, S, D, Q; q to quit; h for help
Message saved
Saving file /home/erik/projects/emacs_build/emacs_git/.git/COMMIT_EDITMSG...
Wrote /home/erik/projects/emacs_build/emacs_git/.git/COMMIT_EDITMSG
Git finished

Configured features:
XPM JPEG TIFF GIF PNG SOUND GPM DBUS GSETTINGS GLIB NOTIFY INOTIFY
LIBSELINUX GNUTLS FREETYPE HARFBUZZ XFT ZLIB TOOLKIT_SCROLL_BARS GTK3
X11 XDBE XIM MODULES THREADS PDUMPER GMP

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: C/*l

Minor modes in effect:
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  auto-revert-mode: t
  flymake-mode: t
  lsp-diagnostics-mode: t
  company-mode: t
  lsp-headerline-breadcrumb-mode: t
  lsp-modeline-workspace-status-mode: t
  lsp-modeline-diagnostics-mode: t
  lsp-modeline-code-actions-mode: t
  bug-reference-prog-mode: t
  lsp-completion-mode: t
  lsp-managed-mode: t
  lsp-mode: t
  projectile-mode: t
  helm-mode: t
  helm-minibuffer-history-mode: t
  shell-dirtrack-mode: t
  helm--remap-mouse-mode: t
  async-bytecomp-package-mode: t
  global-highlight-parentheses-mode: t
  highlight-parentheses-mode: t
  global-linum-mode: t
  linum-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t
  abbrev-mode: t
  hs-minor-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug sendmail helm-command helm-elisp
helm-eval edebug backtrace find-func helm-info clang-format magit-extras
goto-addr mule-util face-remap magit-submodule magit-obsolete
magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull
magit-fetch magit-clone magit-remote magit-commit magit-sequence
magit-notes magit-worktree magit-tag magit-merge magit-branch
magit-reset magit-files magit-refs magit-status magit magit-repos
magit-apply magit-wip magit-log magit-diff smerge-mode diff git-commit
log-edit message rfc822 mml mml-sec epa gnus-util rmail rmail-loaddefs
text-property-search mm-decode mm-bodies mm-encode mail-parse rfc2231
rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils
gmm-utils mailheader pcvs-util add-log magit-core magit-autorevert
autorevert magit-margin magit-transient magit-process with-editor server
magit-mode transient magit-git magit-base which-func ido magit-section
benchmark crm compat-27 compat-26 compat compat-macs flymake-cc
flymake-proc flymake lsp-diagnostics company-oddmuse company-keywords
make-mode company-etags etags fileloop generator company-gtags
company-dabbrev-code company-dabbrev company-files company-clang
company-capf company-cmake company-semantic company-template
company-bbdb company lsp-headerline lsp-icons lsp-modeline lsp-lens
vc-git diff-mode bug-reference view lsp-zig lsp-steep lsp-svelte
lsp-sqls lsp-ruby-syntax-tree lsp-yaml lsp-xml lsp-vimscript lsp-vhdl
lsp-volar lsp-vetur lsp-html lsp-verilog lsp-vala lsp-v lsp-typeprof
lsp-ttcn3 lsp-toml lsp-terraform lsp-tex lsp-sorbet lsp-solargraph
lsp-rust lsp-rf lsp-remark lsp-racket lsp-r lsp-purescript lsp-pylsp
lsp-pyls lsp-pwsh lsp-php lsp-perlnavigator lsp-perl lsp-openscad
lsp-ocaml lsp-magik lsp-nix lsp-nim lsp-nginx lsp-marksman lsp-markdown
lsp-lua lsp-kotlin lsp-json lsp-javascript lsp-idris lsp-haxe lsp-groovy
lsp-hack lsp-graphql lsp-gleam lsp-go lsp-completion lsp-gdscript
lsp-fsharp lsp-fortran lsp-eslint lsp-erlang lsp-emmet lsp-elixir
lsp-elm lsp-dockerfile lsp-dhall lsp-d lsp-css lsp-csharp gnutls
lsp-crystal lsp-cmake lsp-clojure lsp-semantic-tokens lsp-clangd dom
lsp-beancount lsp-bash lsp-ansible lsp-angular lsp-ada lsp-actionscript
lsp-mode lsp-protocol yasnippet-snippets yasnippet xref project
tree-widget wid-edit spinner network-stream puny nsm rmc markdown-mode
noutline outline lv imenu ht inline f ewoc epg epg-config hideshow
cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine
cc-vars cc-defs image-file winner helm-external helm-net url url-proxy
url-privacy url-expand url-methods url-history url-cookie url-domsuf
mailcap tramp-archive tramp-gvfs url-util dbus xml spaceline-config
spaceline-segments s spaceline powerline powerline-separators color
powerline-themes dash rx helm-projectile warnings projectile skeleton
ibuf-macs find-dired lisp-mnt grep compile ibuf-ext ibuffer
ibuffer-loaddefs helm-mode helm-misc helm-files image-dired image-mode
exif filenotify dired-x dired-aux dired dired-loaddefs ffap thingatpt
tramp tramp-loaddefs trampver tramp-integration files-x tramp-compat
shell pcomplete comint ring parse-time iso8601 time-date ls-lisp
helm-buffers helm-occur helm-tags helm-locate helm-grep helm-regexp
format-spec ansi-color helm-utils helm-help helm-types helm
helm-global-bindings helm-easymenu helm-core async-bytecomp helm-source
helm-multi-match helm-lib async helm-config highlight-parentheses
xterm-color linum manoj-dark-theme use-package-bind-key bind-key neotree
advice pcase edmacro kmacro general easy-mmode cl-extra help-mode
use-package-ensure use-package-core derived finder-inf info package
easymenu browse-url url-handlers url-parse auth-source cl-seq eieio
eieio-core cl-macs eieio-loaddefs password-cache json subr-x map
url-vars seq byte-opt gv bytecomp byte-compile cconv cl-loaddefs cl-lib
tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type
mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode elisp-mode
lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch
timer select scroll-bar mouse jit-lock font-lock syntax facemenu
font-core term/tty-colors frame minibuffer cl-generic cham georgian
utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean
japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european
ethiopic indian cyrillic chinese composite charscript charprop
case-table epa-hook jka-cmpr-hook help simple abbrev obarray
cl-preloaded nadvice loaddefs button faces cus-face macroexp files
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget hashtable-print-readable backquote threads dbusbind
inotify dynamic-setting system-font-setting font-render-setting
move-toolbar gtk x-toolkit x multi-tty make-network-process emacs)

Memory information:
((conses 16 1056094 118790)
 (symbols 48 48788 1)
 (strings 32 140835 10073)
 (string-bytes 1 4818683)
 (vectors 16 70471)
 (vector-slots 8 2690660 1120416)
 (floats 8 407 502)
 (intervals 56 7515 1257)
 (buffers 1000 31))
From 4936db1abb4137046cdd02d9be568c3e16d241cb Mon Sep 17 00:00:00 2001
From: Erik van Zwol <[email-masked]>
Date: Sun, 21 Aug 2022 21:36:11 -0600
Subject: [PATCH] ; * src/xdisp.c (hscroll_window_tree): hscroll current-line
 fix

---
 src/xdisp.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/xdisp.c b/src/xdisp.c
index 0248e8e53f..6719a858f7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -15888,7 +15888,11 @@ hscroll_window_tree (Lisp_Object window)
 				      : (text_area_width / 2))))
 		    	  / FRAME_COLUMN_WIDTH (it.f);
 	      else if ((!row_r2l_p
-			&& w->cursor.x >= text_area_width - h_margin)
+			&& (w->cursor.x >= text_area_width - h_margin
+			    /* When hscrolling only the current line and the current line
+			       is less than (text_area_width - h_margin), it might be hscrolled
+			       almost completely off the left side unless we catch it here.  */
+			    || hscl))
 		       || (row_r2l_p && w->cursor.x <= h_margin))
 		{
 		  if (hscroll_relative_p)
-- 
2.25.1