Skip to content

This Emacs package provides functions designed to visually distinguish the currently selected window by applying a unique accent color to its fringes, mode line, header line, and margins.

License

Notifications You must be signed in to change notification settings

captainflasmr/selected-window-accent-mode

Repository files navigation

selected-window-accent-mode

Summary

The Selected Window Accent Mode is an Emacs package designed to visually distinguish the currently selected window by applying a unique accent color to its fringes, mode line, header line, and margins.

img/selected-window-accent-mode-00.jpg

Whats New

v1.0.0 <2024-10-19>

feat: add function to sync tab-bar faces with current theme

  • Introduced `selected-window-accent-sync-tab-bar-to-theme`, which synchronizes the tab-bar faces (tab, tab-inactive) with the current theme.
    • Sets the tab-bar face background and foreground to match the current `default` face settings.
  • Added “Tab Sync to Theme” option under “Other” actions in the selected-window-accent hydra.

First full version.

v0.9.5 <2024-08-24>

Enhanced selected-window-accent functionality with blending options

This means that not only will the modeline, fringes and header be accent colored, but also the whole selected window background color, tinted to the alpha chosen.

  • Introduced selected-window-accent-use-blend-background and selected-window-accent-use-blend-alpha to allow blending of the accent color with the background of the selected window a selected alpha amount.
  • Introduced new toggle functions and added to transient:
    • selected-window-accent-toggle-blend-background
    • selected-window-accent-toggle-pywal
  • Added function selected-window-accent-blend-colors to support blending of two colors.
  • Updated selected-window-accent--set-foreground-color and selected-window-accent functions to incorporate new blending feature.
  • Improved existing functions for setting and toggling accent features, ensuring consistent style and formatting.
  • Cleaned up indentation and formatting inconsistencies across the file for better readability.

Example use of new selected window blending functionality:

Note: that currently there are some limitations, and in fact the same ones that apply to general tiling outline borders - see Limitations section.

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 10)
  (selected-window-accent-use-blend-background t)
  (selected-window-accent-use-blend-alpha 0.2)
  (selected-window-accent-tab-accent t)
  (selected-window-accent-custom-color "cyan4")
  (selected-window-accent-mode-style 'default))

img/selected-window-accent-mode-07.jpg

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 10)
  (selected-window-accent-use-blend-background t)
  (selected-window-accent-use-blend-alpha 0.1)
  (selected-window-accent-tab-accent t)
  (selected-window-accent-custom-color "orange")
  (selected-window-accent-mode-style 'subtle))

img/selected-window-accent-mode-08.jpg

v0.9.1 <2024-08-13>

Added explicit (require ‘transient)

v0.9.0 <2024-08-10>

Add Pywal color integration to selected-window-accent-mode to allow the accent color to be consistent with the wallpaper of the operating system.

Note: will only work on linux.

  • Introduce `selected-window-accent-use-pywal` option to use a Pywal-generated color palette.
  • Add `selected-window-accent–get-pywal-color` function to fetch colors from Pywal palette.
  • Update logic in `selected-window-accent` function to use Pywal color if enabled.
  • Require `json` package for handling Pywal palette.

Pywal is a tool on linux that generates color schemes from images, allowing users to apply these colors to their desktop and application themes for a cohesive and dynamic look.

Example use:

(setq selected-window-accent-use-pywal t)

When enabled, color1 is selected as the accent color, taken from the file : ~/.cache/wal/colors.json which is a generic color file typically generated by pywal.

This means that the accent color can be more tied in with the current wallpaper once pywal is connected to the wallpaper change mechanism of your operating system.

Note that this feature will require an external pywal generation step, triggered on wallpaper change, examples given below.

See below for an example colors.json file

Technically any tool that can write to a json file in a similar format will have a carry through affect on the accent color associated with this package. Here is an example :

{
    "wallpaper": "/home/jdyer/.last_wallpaper.jpg",
    "alpha": "100",

    "special": {
        "background": "#0d1a05",
        "foreground": "#c8cfdb",
        "cursor": "#c8cfdb"
    },
    "colors": {
        "color0": "#0d1a05",
        "color1": "#8FA944",
        "color2": "#165E97",
        "color3": "#5C7391",
        "color4": "#748AA6",
        "color5": "#7498C4",
        "color6": "#8D9BB1",
        "color7": "#c8cfdb",
        "color8": "#8c9099",
        "color9": "#8FA944",
        "color10": "#165E97",
        "color11": "#5C7391",
        "color12": "#748AA6",
        "color13": "#7498C4",
        "color14": "#8D9BB1",
        "color15": "#c8cfdb"
    }
}

On linux, install python-pywal using your package manager of choice.

At which point you can generate a colors.json with the following commands:

wal -c
wal -i ~/.last_wallpaper.jpg -q -n

Wallpaper Change Example

Changing a wallpaper and hooking pywal up accordingly, which technically should work for both Wayland and X11.

#!/bin/bash

wallpaper_path="$(find ~/wallpaper-dir -type f | shuf -n 1)"
echo $wallpaper_path > ~/.last_wallpaper_path
cp -f $wallpaper_path ~/.last_wallpaper.jpg

if [[ $XDG_SESSION_TYPE == "x11" ]]; then
   feh --bg-scale "$wallpaper_path"
fi

if [[ $XDG_SESSION_TYPE == "wayland" ]]; then
   swww img "$wallpaper_path" --transition-step 20 --transition-fps=20
fi

# lets run pywal for color scheme generation
wal -c
wal -i ~/.last_wallpaper.jpg -q -n

v0.8.1 <2024-08-03>

feat: Add transient dependency and fix indentation

  • Added ‘transient’ package requirement to `Package-Requires` in the header.
  • Fixed indentation inconsistencies across the file for better code readability.

Details:

  • Added `transient` package dependency:
    • Updated the header to include `(transient “0.1.0”)` in `Package-Requires`.

v0.8.0 <2024-07-15 Mon>

  • Added transient menu for interactive adjustments (see README usage)
  • Upgraded emacs dependency to 28.1.
  • Added `selected-window-accent-fg-color` for custom foreground accent color.
  • Introduced various `defcustom` options for finer control over foreground accent:
    • `selected-window-accent-foreground-adjust-factor`
    • `selected-window-accent–use-complementary-color`
    • `selected-window-accent–foreground-invert-state`
    • `selected-window-accent–foreground-offset`
  • Implemented functions for adjusting foreground brightness:
    • `selected-window-accent-flip-foreground-color`
    • `selected-window-accent-increment-foreground-color`
    • `selected-window-accent-decrement-foreground-color`
    • `selected-window-accent-toggle-complementary-color`
    • `selected-window-accent-toggle-tab-accent`
    • `selected-window-accent-toggle-smart-borders`
  • Provided a function to output current settings for copy and paste to emacs init file: `selected-window-accent-output-selected-window-accent-settings`
  • Miscellaneous improvements and refactoring.

Quick Start

To use left and bottom accent based on the themes highlight color:

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 10)
  (selected-window-accent-custom-color nil)
  (selected-window-accent-mode-style 'subtle))

OR define your own color:

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 10)
  (selected-window-accent-custom-color "#427900")
  (selected-window-accent-mode-style 'subtle))

Installation

use-package (MELPA)

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1))

use-package (emacs 30+)

Put the following into your emacs init file:

(use-package selected-window-accent-mode
  :vc (:fetcher github :repo "captainflasmr/selected-window-accent-mode")
  :config (selected-window-accent-mode 1))

From source

Download the `.el` file and place it in your Emacs `load-path`.

Then either manually load it or add it to your configuration to be loaded at startup.

(require 'selected-window-accent-mode)
(selected-window-accent-mode 1)

Usage

Interactively Toggle the mode on and off M-x selected-window-accent-mode

A transient map is available (Emacs 28.1+):

(eval-after-load 'selected-window-accent-mode
  '(progn
     (define-key global-map (kbd "C-c w") 'selected-window-accent-transient)))

which will bring up the following transient menu:

img/selected-window-accent-mode-transient-menu.jpg

The styles that are currently supported :

  • default
  • tiling
  • subtle

Examples

Example 1 - Default / custom color

img/selected-window-accent-mode-01.jpg

To enable the accent mode automatically upon starting Emacs, add the following line to your `.emacs` or `init.el` file:

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 20)
  (selected-window-accent-custom-color "goldenrod")
  (selected-window-accent-mode-style 'default))

This will accent the modeline only for the selected window with the goldenrod color.

Example 2 - Tiling / custom color / custom fringe thickness

img/selected-window-accent-mode-02.jpg

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 6)
  (selected-window-accent-custom-color "#4179b2")
  (selected-window-accent-mode-style 'tiling))

This will accent the full outline of the window with the color #4179b2 more akin to a tiling window manager.

Example 3 - Tiling / theme highlight color

Example is using the theme doom-one

jimg/selected-window-accent-mode-03.jpg

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 10)
  (selected-window-accent-custom-color nil)
  (selected-window-accent-mode-style 'tiling))

This will accent the full outline of the window with the highlight color taken from the current theme.

Example 4 - Subtle / custom fringe thickness (thick)

Example is using the theme doom-one

img/selected-window-accent-mode-04.jpg

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 20)
  (selected-window-accent-custom-color nil)
  (selected-window-accent-mode-style 'subtle))

This will accent the modeline and just the left fringe and in this case be quite a pronounced thick accent.

Example 5 - Subtle / theme accent color with darkening and desaturation

Example is using the theme doom-one

The takes the default highlight color from the theme as before but applies darkening and desaturation.

img/selected-window-accent-mode-05.jpg

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 20)
  (selected-window-accent-percentage-darken 10)
  (selected-window-accent-percentage-desaturate 100)
  (selected-window-accent-custom-color nil)
  (selected-window-accent-mode-style 'subtle))

Example 6 - Subtle / theme accent color with lightening and saturation and tab accent

Example is using the theme doom-one

The takes the default highlight color from the theme as before but applies lightening and saturation along with the same color tab accent.

img/selected-window-accent-mode-06.jpg

(use-package selected-window-accent-mode
  :config (selected-window-accent-mode 1)
  :custom
  (selected-window-accent-fringe-thickness 20)
  (selected-window-accent-percentage-darken -10)
  (selected-window-accent-percentage-desaturate -100)
  (selected-window-accent-tab-accent t)
  (selected-window-accent-custom-color nil)
  (selected-window-accent-mode-style 'subtle))

Customization

Custom variableDescription
selected-window-accent-foreground-adjust-factorAdjustment factor for incrementing or decrementing foreground color brightness.
selected-window-accent-mode-styleCurrent style for accenting the selected window.
selected-window-accent-percentage-darkenThe percentage the highlight accent is darkened.
selected-window-accent-use-blend-backgroundWhen non-nil, use the accent color to blend with background of selected window.
selected-window-accent-use-pywalWhen non-nil, use a color from Pywal generated palette.
selected-window-accent-smart-bordersWhen non-nil, the `selected-window-accent-smart-borders` is active.
selected-window-accent-fg-colorCustom foreground accent color for the selected window.
selected-window-accent-custom-colorCustom accent color for the selected window.
selected-window-accent-percentage-desaturateThe percentage the highlight accent is saturated.
selected-window-accent-modeNon-nil if Selected-Window-Accent mode is enabled.
selected-window-accent-use-blend-alphaAdjustment alpha factor for background of selected window blending.
selected-window-accent-tab-accentWhen non-nil, the `selected-window-accent-tab-accent` is active.
selected-window-accent-mode-hookHook run after entering or leaving `selected-window-accent-mode’.
selected-window-accent-fringe-thicknessThe thickness of the fringes in pixels.

Commands

selected-window-accent–reset-window-accentReset the accent colors for all windows to their defaults.
selected-window-accent-sync-tab-bar-to-themeSynchronize tab-bar faces with the current theme.
selected-window-accent-switch-selected-window-accent-styleSwitch the selected window accent style to STYLE and apply it.
selected-window-accent-increment-foreground-colorIncrement the foreground color brightness. With ARG, adjust by a larger factor.
selected-window-accent-decrement-foreground-colorDecrement the foreground color brightness. With ARG, adjust by a larger factor.
selected-window-accent-flip-foreground-colorFlip the current foreground color to its opposite value.
selected-window-accent-output-selected-window-accent-settingsOutput current `selected-window-accent-mode’ settings to a new buffer.
C-c wselected-window-accent-transientTransient for selected window accent.
selected-window-accent-toggle-tab-accentToggle between showing the tab accent.
C-q aselected-window-accent-modeToggle selected window accenting.
selected-window-accent-toggle-pywalToggle between pywal.
selected-window-accent-switch-accent-colorSwitch the selected window accent color and apply it.
selected-window-accent-toggle-blend-backgroundToggle between blend background.
selected-window-accent-toggle-smart-bordersToggle between smart borders.
selected-window-accent-toggle-complementary-colorToggle between complementary color for foreground based on background color.

Minor Mode

The selected-window-accent-mode is a global minor mode that you can toggle to enable or disable the accenting of the selected window.

When enabled, it distinguishes the selected window with a special accent color.

Hooks

Two hooks are used to automatically update the window accents when the window configuration or state changes:

  • window-configuration-change-hook
  • window-state-change-hook

These are added when the selected-window-accent-mode is enabled and removed when disabled.

Design / Algorithm / Limitations

Just as a note, the overall design of this package is a little, lets just say clunky, something that has been somewhat shoehorned into the Emacs functional architecture, therefore there will be a few little quirks. In this section I look to explain my general design ideas regarding how I achieved some kind of window highlighting / accenting and the associated limitations.

This section is mainly for me, as the maintainer of this package, but may be informative to others. This section is to try and fully understand how I have designed this thing for when I come back and have another rethink on improvements.

Firstly it is important to define the scope of window based visual highlighting in Emacs, which hopefully will help to explain some of the limitations of this package.

It works well enough I think at the moment and I especially I tend to favour the ‘subtle accent mode which inherently has the fewest issues along with providing a satisfying visually distinguishing highlighting mechanism, more bang for the buck if you will.

Emacs repurposed elements

fringe

position: left, right face-attribute: ‘fringe : all-windows size: (set-window-fringes left right) : per-window

header-line

position: top value: header-line-format : per-window face-attribute: ‘header-line : all-windows size: face-attribute :height : all-windows

mode-line

position: bottom value: mode-line-format : selected-window face-attribute: ‘mode-line-active : selected-window size: face-attribute :height : all-windows

tab-bar

face-attribute: ‘tab-bar-tab

Pseudo-code

calculate accent colors
update global face-attributes

walk-windows
  for each window
    update window with accent or default appearance
    if window is not selected
      reset header-line to nil
      reset fringes to 0

Limitations

As a header-line can only have a single global color it does mean that the header-line-format for each window needs to be made blank in order to preserve accent consistency, this means that modes which change the header-line, such as some modes of magit and org-sticky-header will possibly have to be sacrificed for this selected-window-accent-mode to function coherently.

There is a possibility that I could add in some extra logic depending on the mode that is set, but that might be for a future version, and at this moment I’m just not sure the effort is worth it.

The accent is now always alongside an Emacs default margin so as not to overlap with existing packages that utilize the window margin settings, this would make the accent facility look a little less visually appealing then applying a little margin for the selected window along with a compensating margin for non selected windows, but this will have to be sacrificed for not disrupting other Emacs package functionality.

All non selected windows have been fringe zeroed to preserve fringe accent consistency as the fringe color can only be set globally meaning that any Emacs packages that implement fringe functionality, which I have found to be uncommon, would show varying levels of window accents.

When a buffer is split into multiple windows in tiling mode the header line is shared, thus leading to an accented header line across all splits, this is an inherent limitation of Emacs and how it processes windows / buffers.

Phew!, that might be it, this can get quite complicated!

What about overlays?

At the moment this package works well enough for my needs and I will think about overlays again at some point to see if I can somehow re-purpose them to fit my needs, currently it is the buffer / window scrolling that I think would always tend to look pretty clunky if implemented.

The Future

I of course shall keep an eye on Emacs development to see if at some time in the future a more flexible per window visual facility becomes available.

ISSUES

TODODOINGDONE
ISSUE #6 - Feature request: accent currently se…ISSUE #4 - Doesn’t work well with other packagesISSUE #1 - Do not apply highlighting when frame…
Limiting magit-log when enabledISSUE #3 - Package breaks fringes
Add pywal toggle to transient
blend accent color into selected window background
Added pywal integration
Restore modeline height when switching between …
Define accent color saturation adjustment
Define accent color darken adjustment
Highlight selected tab with same accent color
Add to MELPA
Minor change to properly format color-theme-buf…
Pacified package-lint with visual-fill-column 0.0
Added similar package comparisons as suggested
Rename color-name-to-hex to selected-window-acc…
Fixing issues to be able to submit to MELPA
Images to img directory and referenced from README
Expand emacs help / documentation
Add GNU header
Cope better with 0 thickness
Add ChangeLog.
isual-fill-column-mode not working again!
Improve modeline contrast between fg and bg

ROADMAP

TODODOING
Incorporate mode-line-active and mode-line-inactive
Header-line not shown on window split
Adjust the not selected-window margin to avoid little window navigation. disruption
Excess selected-window disruption in header-line. (not sure I can do much about this)
Add some form of unit test

ISSUES (github)

ISSUE #6 - Feature request: accent currently selected/focused frame

If multiple Emacs frames exist, then the selected window in each will be accented. It would be nice if the currently selected/focused frame was accented more than non-focused frames.

ISSUE #4 - Doesn’t work well with other packages

olivetti & org-sticky-header broken with selected-window-accent-mode

I have decided to disable the setting of windows margins as part of this package as this is often used for padding in other packages. This means I can now let packages such as olivetti-mode and visual-fill-column do their own thing without any margin interference. Therefore this package will mainly achieve its functionality via fringe modification rather than fringe/margins.

The disadvantage of this is that on window transition there will be more of a text in buffer offset shift as the select-window-accent-mode fringe is applied to the select window without a default compensatory margin / fringe shift. This didn’t really work anyway and there was always a little shift depending on the width of the native emacs margin character vs fringe pixel size.

This means I don’t have to depend on package checks and maybe packages I am unaware of that depend on window buffer margin changes will work better in the future.

Maybe I can just define a non selected window compensatory margin in the future, for now I will leave as is and see how it goes!

However this currently doesn’t cover any mode that modifies a window header, like for example org-sticky-header.

ISSUE #1 - Do not apply highlighting when frame only contains 1 window

ISSUE #3 - Package breaks fringes

ISSUES (other)

Limiting magit-log when enabled

Add pywal toggle to transient

blend accent color into selected window background

Added pywal integration

Restore modeline height when switching between modes

Define accent color saturation adjustment

Define accent color darken adjustment

Highlight selected tab with same accent color

Add to MELPA

Minor change to properly format color-theme-buffer-local

Pacified package-lint with visual-fill-column 0.0

Added similar package comparisons as suggested

Rename color-name-to-hex to selected-window-accent–color-name-to-hex

Fixing issues to be able to submit to MELPA

  • byte-compile / flycheck
  • checkdoc
  • package-lint
  • other

Images to img directory and referenced from README

Expand emacs help / documentation

Add GNU header

Cope better with 0 thickness

Add ChangeLog.

isual-fill-column-mode not working again!

Improve modeline contrast between fg and bg

ROADMAP

Incorporate mode-line-active and mode-line-inactive

This would make more sense especially in the ‘default mode. So in-built Emacs modeline functionality would come into play.

Header-line not shown on window split

I have a funny feeling this could be very difficult, if not impossible!

Adjust the not selected-window margin to avoid little window navigation. disruption

Hence translating a fringe pixel width to a number of margin characters, not quite sure how I am going to do this yet.

Excess selected-window disruption in header-line. (not sure I can do much about this)

Add some form of unit test

Testing

See CHANGELOG.org

Alternative window highlighting packages

There exist a few Emacs packages that perform window highlighting but that don’t quite provide the feature set of selected-window-accent.

selected-window-accent focusses more on clearly but non-intrusively highlighting the currently selected/focussed window by highlighting aspects of the window border without having to modify the appearance of non-selected windows, hence more akin to a tiling window manager.

dimmer

“This package provides a minor mode that indicates which buffer is currently active by dimming the faces in the other buffers.”

This is the closest in functionality to selected-window-accent, the difference being that dimmer dims non selected windows rather than accent the selected window.

dimmer can be used in conjunction and will complement selected-window-accent to further enhance the emphasizing of the selected window.

hiwin

“This package provides a minor-mode to change the background color of the non active window.”

It uses overlays to highlight non active windows, so is similar to dimmer but is less subtle in its highlighting mechanism and hasn’t been updated in excess of 10 years.

color-theme-buffer-local

“This package lets you set a color-theme on a per-buffer basis.”

Unlike dimmer and hiwin this package isn’t related to the concept of a selected window but more of defining different themes for different windows to distinguish them.

solaire-mode

“This package is designed to visually distinguish “real” buffers (i.e. file-visiting code buffers where you do most of your work) from “unreal” buffers (like popups, sidebars, log buffers, terminals, etc) by giving the latter a slightly different – often darker – background”

Unlike dimmer and hiwin this package isn’t related to the concept of a selected window but more of distinguishing between collections of IDE like elements within Emacs.

Contributing

Contributions to arscript-mode are welcome! Whether it’s bug reports, feature suggestions, or code contributions, feel free to reach out or submit pull requests on GitHub.

About

This Emacs package provides functions designed to visually distinguish the currently selected window by applying a unique accent color to its fringes, mode line, header line, and margins.

Resources

License

Stars

Watchers

Forks

Packages

No packages published