{"id":21291686,"url":"https://github.com/jdtsmith/mlscroll","last_synced_at":"2026-01-26T21:51:59.025Z","repository":{"id":41062814,"uuid":"363726120","full_name":"jdtsmith/mlscroll","owner":"jdtsmith","description":"Lightweight scrollbar for the Emacs mode line","archived":false,"fork":false,"pushed_at":"2025-01-12T14:47:14.000Z","size":119,"stargazers_count":102,"open_issues_count":2,"forks_count":9,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-15T16:36:15.693Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdtsmith.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-02T18:49:27.000Z","updated_at":"2025-02-10T18:37:34.000Z","dependencies_parsed_at":"2023-12-12T20:32:52.569Z","dependency_job_id":"fe040400-12f4-427b-a550-4cef38989c75","html_url":"https://github.com/jdtsmith/mlscroll","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/jdtsmith/mlscroll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fmlscroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fmlscroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fmlscroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fmlscroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdtsmith","download_url":"https://codeload.github.com/jdtsmith/mlscroll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fmlscroll/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28789186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T21:49:50.245Z","status":"ssl_error","status_checked_at":"2026-01-26T21:48:29.455Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-21T13:39:17.289Z","updated_at":"2026-01-26T21:51:54.016Z","avatar_url":"https://github.com/jdtsmith.png","language":"Emacs Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n# MLScroll - Modeline Scrollbar for Emacs\n\u003cimg alt=\"MELPA\" src=\"https://melpa.org/packages/mlscroll-badge.svg\"/\u003e\nA lightweight scrollbar for the Emacs mode line. \n\nFor graphical window systems:\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;![mlscroll](https://user-images.githubusercontent.com/93749/116825204-38031880-ab5c-11eb-8252-5f60a61f45dd.gif)\n\nand terminals too:\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;![mlscroll_terminal](https://github.com/user-attachments/assets/1b553973-bae0-465e-98c2-364d58457a69)\n\n\n## Why?\n\nEmacs has so many great ways to navigate, I really only ever used scroll-bars as a _visual indication of position and file size_.  But recently, to save space, I added `(scroll-bar-mode -1)` to my init.  Immediately I missed having that information at a glance.  A percentage in the mode line (like `25%`) is not very glanceable, and also gives no information about the ratio of the currently visible content relative to the total line length (i.e. the _length_ of the bar).  I wanted something very fast and very lightweight, plus I'm not so into [rainbow cats](https://github.com/TeMPOraL/nyan-mode).  Hence MLScroll.\n\n## Info\n\n- Uses [_specified space_](https://www.gnu.org/software/emacs/manual/html_node/elisp/Specified-Space.html) for drawing (only 3 variable-width spaces, actually) for super-fast text-based mode line scroll indication.\n- The bar lengths convey the number of _lines_ above/visible/below window. Computes line numbers with caching for performance.\n- Works in terminals! Terminal graphics are more granular (the minimum \"pixel\" is one character wide).  You might want to increase `mlscroll-width-chars` there. \n- In graphical Emacs, you can interact with the mode line scroll bar — click, click + drag, and wheel-scroll a full window height at a time.\n- Another useful feature: clicking on an inactive window's mode line scroll bar scrolls it, but does _not_ activate that window. \n\n## Installing\n\nGet it from MELPA, and arrange to have:\n\n```elisp\n(mlscroll-mode 1)\n```\n\ncalled at init time (or whenever you are feeling scrolly). Toggle on or off anytime. \n\nExample for `use-package`:\n\n```elisp\n(use-package mlscroll\n  :ensure t\n  :config\n  (setq mlscroll-shortfun-min-width 11) ; truncate which-func\n  (mlscroll-mode 1))\n```\n\nAlternatively, if you start emacs using the command line `--daemon` command (see below):\n\n```elisp\n(use-package mlscroll\n   :ensure t\n   :hook (server-after-make-frame . mlscroll-mode))\n```\n\n## Setup\n\n### Customization\n\nUse `M-x customize-group mlscroll` to change background colors, overall scroll bar width, minimum current \"thumb\" width, border size, and other settings.\n\n### Position\n\nBy default, `MLScroll` disables the `XX%` position mode line indication, and puts itself in the mode line variable `mode-line-end-spaces`, prepending a spacer to right-align itself.  Optionally, it can instead replace the `XX%` indicator (or be placed anywhere in your mode line).  See `mlscroll-alter-percent-position` and `mlscroll-right-align`.\n\n### Which-function mode \n\nThe builtin `which-function-mode` by default puts `[full-function-name]` on the right side of the mode line.  With long names and the default bar placement, this can push the `MLScroll` bar partially or fully off the mode line.  Set `mlscroll-shortfun-min-width` to a minimum width, and `MLScroll` will truncate the `which-function` name to at least that many trailing characters (e.g. `[…function-name]` or similar), to make room for the scrollbar.  The amount of truncation can be adjusted using `mlscroll-shortfun-extra-width`. \n\n### Integrating with the mode-line \n\nNote that `MLScroll` is most visually compatible with \"plain\" mode line formats that don't use `:box` bordering.  It will warn you if you try to use a border with a `:box`-full format enabled (removing the border).  It also doesn't inherit `:underline` and `:overline` mode line properties unless `mlscroll-border` is set to 0 (these don't work with the combination of specified space and `:box`).\n\nSee the suggestions for configuring [moody](https://github.com/tarsius/moody) for some config ideas. \n\nFor users of `modus-themes`, `(setq modus-themes-mode-line '(moody borderless))` is recommended, or, in more recent versions (\u003ev4):\n\n```elisp\n(setq modus-themes-common-palette-overrides\n      '((border-mode-line-active unspecified)\n        (border-mode-line-inactive unspecified)))\n```\n\n## Scroll-bar width: Lines vs. Characters\n\nThe `MLScroll` bar widths are based on the number of _lines_ visible in the window (+ lines before and after it). The normal scroll bar is based on _characters_ shown. Both tend to change as very long/wrapped lines come into view, but in the opposite sense: `MLScroll` sees fewer lines shown and shrinks the current thumb; the default scrollbar sees many characters come in view, and grows it.  I find the lines approach to be more sensible, and it has the advantage that with `truncate-lines` on, the thumb doesn't change size as you scroll.  If you'd like to see the difference, evaluate `(insert (make-string 5000 ?a) \"\\n\")` in the `*scratch*` buffer amidst other normal text, and scroll through before and after `toggle-truncate-lines`.  On the other hand, highly folded documents like org-mode docs will show a changing \"thumb size\" as you scroll through, as the current window could contain _many_ (hidden) lines. I find that pretty convenient actually.\n\n## FAQ's\n\n- **How does it work?** `MLScroll` places itself by default in `mode-line-end-spaces`, and uses a right-aligned space to align it at the end of the modeline.  For drawing the bars themselves, it uses three \"specified spaces\".\n\n- **`MLScroll` doesn't work with my fancy mode line mode!** It should work automatically for simple mode lines that end in `mode-line-end-spaces`.  If you prefer,  set `mlscroll-right-align` to `nil` and `mlscroll-alter-percent-position` to `'replace` to put it in place of the `XX%` percentage indicator.  Otherwise, e.g. if you have a highly customized or pre-packaged mode line, you'll need to find somewhere to put `MLScroll`.  A general recipe is to:\n\t1. Set `mlscroll-right-align` to `nil`.\n\t2. Set the mode line scroller into the relevant mode-line variable directly yourself, like so: `(setq fancy-mode-line-variable-of-some-kind '(:eval (mlscroll-mode-line))`. \n\t3. Alternatively, if you didn't design your mode line yourself or find this too complicated, ask whoever did to support `MLScroll`. \n\n- **`MLScroll` starts off very small when I start an emacs session using `--daemon`.** For graphical windows, `MLScroll` needs to know the width of font characters in the mode line (or at least the default font) to draw a pixel-perfect bar. Since `--daemon` doesn't create a frame or know anything about the font widths, loading MLScroll directly under a `--daemon` session misreports the font width as 1 pixel, leading to a very small scroller bar.  The solution is either to abandon `--daemon` in favor of [`(server-start)`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html) in your init file, or arrange for MLScroll to be initialized _later_, after a frame is created, ala:\n  ```elisp\n  (use-package mlscroll\n    :hook (server-after-make-frame . mlscroll-mode))\n  ```\n- **How can I customize MLScroll?** `M-x customize-group mlscroll [Ret]`. \n\n- **I want to use `MLScroll` with different themes throughout the day, what should I do?** This should happen automatically since v0.2.  Since the `MLScroll` \"thumb\" color defaults to the foreground color of the `scroll-bar` face, you might configure that face for your theme, rather than `mlscroll-in-color` directly.\n\n- **I get a message about :box disabling my `MLScroll` border**: `MLScroll` uses the `:box` attribute to draw _border_ (with the help of `:inverse-video`).  If your normal mode line face already has a `:box` property, this will interfere and cause the left/right border to show up.  If you want a border to make your `MLScroll` less tall, consider disabling the `:box` property on faces `'mode-line` and `'mode-line-inactive` (`M-x customized-group mode-line-faces [Ret]`).  See [issue](https://github.com/jdtsmith/mlscroll/issues/3).  For users of `modus-themes`, see above.\n\n## Other tips\n\n`MLScroll` takes up a decent (configurable) chunk of your mode line.  To save space for it even when the window is somewhat narrow, I use:\n\n- [minions](https://github.com/tarsius/minions) to hide all minor-modes under a nice menu.\n- [cyphejor](https://github.com/mrkkrp/cyphejor) to shorten the names of major mode using single-char emoji and greek characters.\n- `(setq mlscroll-shortfun-min-width 11)` to trim down the which-function name as needed. \n- removal of mule-info, and a trim of all double-spaces anywhere in the mode line format to a single space:\n```elisp\n  (setq-default\n   mode-line-format ;less space, no MULE\n   (cl-nsubst-if \" \" (lambda (x) (and (stringp x) (string-blank-p x) (\u003e (length x) 1)))\n\t\t (remove 'mode-line-mule-info mode-line-format))))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdtsmith%2Fmlscroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdtsmith%2Fmlscroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdtsmith%2Fmlscroll/lists"}