diff --git a/private_dot_config/private_fish/functions/private___tide_apply_terminal_appearance.fish b/private_dot_config/private_fish/functions/private___tide_apply_terminal_appearance.fish index 5f23781..f92f571 100644 --- a/private_dot_config/private_fish/functions/private___tide_apply_terminal_appearance.fish +++ b/private_dot_config/private_fish/functions/private___tide_apply_terminal_appearance.fish @@ -1,8 +1,61 @@ -function __tide_apply_terminal_appearance --argument-names appearance +function __tide_apply_terminal_appearance --argument-names appearance background contains -- $appearance dark light or return 2 + # The palette Tide ships is authored for a dark terminal, where every + # segment shares this background. + set -l dark_segment_background 303030 + # The background __tide_terminal_light_color's foregrounds are tuned against, + # and the ratio they are tuned to. + set -l reference_background E4E4E4 + set -l reference_contrast 4.5 + # How far the segment background sits from the terminal background. Set + # $__tide_terminal_segment_contrast to taste: 1.04:1 is what a fixed E4E4E4 + # gave on a warm background and is invisible, 1.4:1 reads heavy. + set -l segment_contrast 1.12 + if string match -qr '^[0-9]+(\.[0-9]+)?$' -- "$__tide_terminal_segment_contrast" + and test (math -s0 "round($__tide_terminal_segment_contrast * 100)") -gt 100 + set segment_contrast $__tide_terminal_segment_contrast + end + # What the foregrounds are re-aimed at. The extra margin over + # $reference_contrast absorbs the rounding back to 8 bits per channel. + set -l foreground_contrast 4.55 + # Used when the terminal will not say what its background is. White is the + # common default for light terminals. + set -l fallback_background FFFFFF + + set -l segment_background + set -l foreground_factor 1 + + if test "$appearance" = light + test -z "$background" + and set background (__tide_terminal_background_color light) + string match -qr '^[0-9A-Fa-f]{6}$' -- "$background" + or set background $fallback_background + set background (string upper -- $background) + + # Place the segment a fixed contrast step below the terminal background, + # so it picks up that background's tint instead of imposing a grey. + set -l background_luminance (math "max(0.000001, "(__tide_relative_luminance $background)")") + set -l segment_luminance (__tide_contrast_ceiling $background_luminance $segment_contrast) + set segment_background (__tide_scale_luminance $background \ + (math "$segment_luminance / $background_luminance")) + + # Every light foreground is tuned to sit at $reference_contrast against + # the reference background, so the palette shares one luminance ceiling. + # A darker segment lowers that ceiling, and moving every foreground by + # the same luminance factor walks them all down to it at once. + set -l reference_ceiling (__tide_contrast_ceiling \ + (__tide_relative_luminance $reference_background) $reference_contrast) + set -l segment_ceiling (__tide_contrast_ceiling \ + (__tide_relative_luminance $segment_background) $foreground_contrast) + set foreground_factor (math "min(1, $segment_ceiling / $reference_ceiling)") + else + set background '' + end + if test "$__tide_terminal_appearance" = "$appearance" + and test "$__tide_terminal_background" = "$background" return 1 end @@ -14,6 +67,14 @@ function __tide_apply_terminal_appearance --argument-names appearance string match -q 'tide_*color*' -- $name or continue + # These overrides are exported, so a Fish started from a Fish that + # already applied a palette inherits them and would otherwise + # capture that palette as its baseline. Dropping the inherited + # global makes the name resolve to its universal value again, which + # is the configured dark palette. Every name here comes from the + # universal scope, so there is always something left to resolve to. + set --erase --global $name + set -l current_value $$name test (count $current_value) -eq 1 or continue @@ -31,11 +92,25 @@ function __tide_apply_terminal_appearance --argument-names appearance for index in (seq (count $__tide_terminal_color_names)) set -l name $__tide_terminal_color_names[$index] set -l color $__tide_terminal_dark_colors[$index] + if test "$appearance" = light - set color (__tide_terminal_light_color $color) + if string match -q '*bg_color*' -- $name + and test (string upper -- $color) = $dark_segment_background + set color $segment_background + else + set -l light_color (__tide_terminal_light_color $color) + set -l dimmed (__tide_scale_luminance $light_color $foreground_factor) + if test -n "$dimmed" + set color $dimmed + else + set color $light_color + end + end end + set --global --export $name $color end set --global __tide_terminal_appearance $appearance + set --global __tide_terminal_background $background end diff --git a/private_dot_config/private_fish/functions/private___tide_contrast_ceiling.fish b/private_dot_config/private_fish/functions/private___tide_contrast_ceiling.fish new file mode 100644 index 0000000..27c70e6 --- /dev/null +++ b/private_dot_config/private_fish/functions/private___tide_contrast_ceiling.fish @@ -0,0 +1,12 @@ +function __tide_contrast_ceiling --argument-names luminance ratio \ + --description 'Print the highest luminance that still meets a contrast ratio against a background' + + string match -qr '^[0-9]+(\.[0-9]+)?$' -- $luminance + or return 1 + string match -qr '^[0-9]+(\.[0-9]+)?$' -- $ratio + or return 1 + + # WCAG contrast is (lighter + 0.05) / (darker + 0.05), so the darkest + # partner a background can carry at a given ratio falls straight out of it. + math "max(0, ($luminance + 0.05) / $ratio - 0.05)" +end diff --git a/private_dot_config/private_fish/functions/private___tide_relative_luminance.fish b/private_dot_config/private_fish/functions/private___tide_relative_luminance.fish new file mode 100644 index 0000000..09058f2 --- /dev/null +++ b/private_dot_config/private_fish/functions/private___tide_relative_luminance.fish @@ -0,0 +1,15 @@ +function __tide_relative_luminance --argument-names hex \ + --description 'Print the WCAG relative luminance of a six-digit hex color' + + string match -qr '^[0-9A-Fa-f]{6}$' -- $hex + or return 1 + + set -l r (string sub --start 1 --length 2 -- $hex) + set -l g (string sub --start 3 --length 2 -- $hex) + set -l b (string sub --start 5 --length 2 -- $hex) + + # sRGB relative luminance. WCAG's piecewise-linear segment for channels + # below 0.04045 is left out: it only applies under 10/255 and shifts the + # result by less than 0.001, which never changes a palette decision here. + math "0.2126 * ((0x$r / 255 + 0.055) / 1.055) ^ 2.4 + 0.7152 * ((0x$g / 255 + 0.055) / 1.055) ^ 2.4 + 0.0722 * ((0x$b / 255 + 0.055) / 1.055) ^ 2.4" +end diff --git a/private_dot_config/private_fish/functions/private___tide_scale_luminance.fish b/private_dot_config/private_fish/functions/private___tide_scale_luminance.fish new file mode 100644 index 0000000..a781ffc --- /dev/null +++ b/private_dot_config/private_fish/functions/private___tide_scale_luminance.fish @@ -0,0 +1,26 @@ +function __tide_scale_luminance --argument-names hex factor \ + --description 'Multiply a color\'s luminance by a factor, keeping its hue and saturation' + + string match -qr '^[0-9A-Fa-f]{6}$' -- $hex + or return 1 + string match -qr '^[0-9]+(\.[0-9]+)?$' -- $factor + or return 1 + + set -l channels + + for start in 1 3 5 + set -l encoded (string sub --start $start --length 2 -- $hex) + # Decode to linear light, scale, re-encode. Scaling there multiplies + # relative luminance by exactly this factor, because luminance is a + # weighted sum of the linear channels. Scaling the encoded channels + # instead would not: sRGB's +0.055 offset makes the error grow as the + # color gets darker, which is where the contrast floor actually bites. + set -l linear "($factor * ((0x$encoded / 255 + 0.055) / 1.055) ^ 2.4)" + set --append channels "round(255 * max(0, min(1, (1.055 * $linear ^ (1 / 2.4)) - 0.055)))" + end + + # One math call per color rather than three: the bytes are packed into a + # single number and printed back out as hex. -s0 truncates, so each + # channel does its own rounding above. + printf %06X (math -s0 "$channels[1] * 65536 + $channels[2] * 256 + $channels[3]") +end diff --git a/private_dot_config/private_fish/functions/private___tide_terminal_background_color.fish b/private_dot_config/private_fish/functions/private___tide_terminal_background_color.fish new file mode 100644 index 0000000..25c315b --- /dev/null +++ b/private_dot_config/private_fish/functions/private___tide_terminal_background_color.fish @@ -0,0 +1,46 @@ +function __tide_terminal_background_color --argument-names appearance \ + --description 'Print the background color kitty is showing for an appearance' + + contains -- $appearance dark light + or return 1 + + functions -q __kitty_config_dir + or return 1 + + set -l config_dir (__kitty_config_dir) + + # kitty gives the *-theme.auto.conf files priority over includes and even + # over --override, so whatever is in them is what the window is actually + # showing -- whether it got there from `kitten themes` or from + # apply-theme-mode.sh pinning a mode. + for file in $config_dir/$appearance-theme.auto.conf $config_dir/no-preference-theme.auto.conf + test -r $file + or continue + + set -l hex (string match -gr '^\s*background\s+#?([0-9A-Fa-f]{6})\s*$' <$file | tail -n 1) + test -n "$hex" + or continue + set hex (string upper -- $hex) + + set -l luminance (__tide_relative_luminance $hex) + test -n "$luminance" + or continue + + # A background that disagrees with the appearance Fish reported means + # we read the wrong file. A pill derived from the wrong background is + # worse than the static fallback, so skip it. + set -l scaled (math -s0 "round($luminance * 1000)") + if test "$appearance" = light + test $scaled -gt 500 + or continue + else + test $scaled -lt 500 + or continue + end + + echo $hex + return 0 + end + + return 1 +end diff --git a/private_dot_config/private_fish/private_docs/private_superpowers/private_specs/private_2026-07-27-tide-terminal-appearance-design.md b/private_dot_config/private_fish/private_docs/private_superpowers/private_specs/private_2026-07-27-tide-terminal-appearance-design.md new file mode 100644 index 0000000..0b05c22 --- /dev/null +++ b/private_dot_config/private_fish/private_docs/private_superpowers/private_specs/private_2026-07-27-tide-terminal-appearance-design.md @@ -0,0 +1,102 @@ +# Tide Terminal Appearance Design + +## Goal + +Keep the existing Tide prompt unchanged except for its colors. The prompt must +follow the active Kitty or Ghostty terminal appearance, update while the shell +is open, and continue to work inside tmux. + +## Non-goals + +- Do not modify Tide's installed functions. +- Do not change prompt items, icons, separators, shape, spacing, or layout. +- Do not infer appearance from macOS. +- Do not share one terminal's appearance with unrelated Fish sessions. + +## Design + +Add one Fish integration file under `conf.d/`. + +Fish 4.8 already negotiates terminal color-scheme notifications with Kitty, +Ghostty, and tmux, consumes the terminal replies, queries the actual background, +and publishes the result as the read-only `fish_terminal_color_theme` variable. +The integration subscribes to changes of that variable instead of parsing raw +terminal input itself. + +The handler changes only Tide color variables: + +- Dark mode keeps the currently configured values exactly. +- Light mode substitutes darker, contrast-safe equivalents for foreground + colors while preserving each color's semantic role, and replaces the shared + segment background `303030` with a shade of the terminal's own background. + +The light segment background is derived rather than fixed. A single neutral +value cannot sit at a usable distance from every light theme -- `E4E4E4` is +1.03:1 against Kaolin Breeze's `EBE8E4`, which is invisible -- and a neutral +grey reads as a foreign object on a warm or cool background. So the handler +reads the background kitty is showing and places the segment a fixed contrast +step below it, which keeps the segment in the theme's own tint. + +That step is a judgement call rather than a threshold, and it is not only about +the segment: the foregrounds are re-aimed at whatever the segment becomes, so a +heavier step darkens the text along with it and the segment starts reading as a +blob. `1.12:1` is the default. `__tide_terminal_segment_contrast` overrides it, +and values that are not a ratio above 1:1 are ignored, since they would put the +segment level with or above its own background. + +kitty's background comes from the `*-theme.auto.conf` files. kitty gives those +priority over includes and over `--override`, so they are what a window is +actually showing however the theme got there. A background whose luminance +contradicts the appearance Fish reported means the wrong file was read, and is +discarded in favour of the fallback. Terminals that are not kitty get the same +treatment against an assumed white background. + +Moving the segment invalidates the foreground palette, because every light +foreground is authored to sit at exactly 4.5:1 against the reference background +`E4E4E4`, leaving no headroom. Since the whole palette shares one luminance +ceiling, a darker segment lowers that ceiling by a single ratio, and every +foreground is multiplied by it. That scaling happens in linear light, where +relative luminance is a weighted sum of the channels and therefore scales +exactly; scaling the encoded channels instead would drift by more as colors get +darker, which is where the contrast floor actually binds. + +The overrides are exported, so a Fish started from a Fish that already applied a +palette inherits them. The capture step drops those inherited globals first, so +each process reads its baseline from the universal scope Tide configures rather +than from its parent's active palette. + +Overrides use exported global scope. This shadows Tide's universal defaults for +the current Fish process and passes the selected palette to Tide's background +rendering subprocess without affecting Fish sessions in other terminal windows. + +After a scheme event, the handler refreshes Tide's cached colors, reloads the +generated prompt functions, and requests a command-line repaint. Reapplying the +current scheme is a no-op. + +## Failure behavior + +On terminals that do not report a usable appearance, +`fish_terminal_color_theme` remains `unknown` and Tide keeps its existing dark +configuration. Fish owns the terminal protocol bytes, so they never become user +key bindings or command-line input. + +## Verification + +Automated Fish tests verify: + +- only Tide color variables change; +- non-color Tide configuration remains identical; +- dark values equal the current configuration; +- light foregrounds meet the chosen contrast threshold against the derived + segment background, on both a theme background and the fallback; +- scaling a color's luminance moves it by the requested factor, whatever its hue; +- the background probe reads the active theme and rejects one that contradicts + the reported appearance; +- exported global overrides reach a child Fish process; +- repeated events are idempotent, and a changed background is not a repeat; +- the integration subscribes to Fish's native terminal-theme variable; +- Fish parses every changed file. + +Pseudo-terminal acceptance tests emulate light/dark terminal responses and +cover both direct Fish and Fish through tmux. Kitty and Ghostty share the +protocol that Fish consumes. diff --git a/private_dot_config/private_fish/private_tests/private_assert_tide_light_contrast.mjs b/private_dot_config/private_fish/private_tests/private_assert_tide_light_contrast.mjs index 4e1110d..6593045 100644 --- a/private_dot_config/private_fish/private_tests/private_assert_tide_light_contrast.mjs +++ b/private_dot_config/private_fish/private_tests/private_assert_tide_light_contrast.mjs @@ -22,7 +22,13 @@ const luminance = (hex) => { ); }; -const backgroundLuminance = luminance('E4E4E4'); +const background = (process.argv[2] ?? 'E4E4E4').toUpperCase(); +if (!/^[0-9A-F]{6}$/.test(background)) { + console.error(`background ${background}: expected a six-digit color`); + process.exit(1); +} + +const backgroundLuminance = luminance(background); const failures = []; for (const line of input.split('\n')) { @@ -40,7 +46,9 @@ for (const line of input.split('\n')) { ); if (ratio < 4.5) { - failures.push(`${dark} -> ${light}: contrast ${ratio.toFixed(2)} is below 4.5`); + failures.push( + `${dark} -> ${light}: contrast ${ratio.toFixed(2)} against ${background} is below 4.5`, + ); } } diff --git a/private_dot_config/private_fish/private_tests/private_fixtures/private_kitty/private_dark-theme.auto.conf b/private_dot_config/private_fish/private_tests/private_fixtures/private_kitty/private_dark-theme.auto.conf new file mode 100644 index 0000000..7767068 --- /dev/null +++ b/private_dot_config/private_fish/private_tests/private_fixtures/private_kitty/private_dark-theme.auto.conf @@ -0,0 +1,3 @@ +# vim:ft=kitty +background #000000 +foreground #FFFFFF diff --git a/private_dot_config/private_fish/private_tests/private_fixtures/private_kitty/private_light-theme.auto.conf b/private_dot_config/private_fish/private_tests/private_fixtures/private_kitty/private_light-theme.auto.conf new file mode 100644 index 0000000..dbbf586 --- /dev/null +++ b/private_dot_config/private_fish/private_tests/private_fixtures/private_kitty/private_light-theme.auto.conf @@ -0,0 +1,3 @@ +# vim:ft=kitty +background #FFFFFF +foreground #000000 diff --git a/private_dot_config/private_fish/private_tests/private_test_tide_terminal_appearance.fish b/private_dot_config/private_fish/private_tests/private_test_tide_terminal_appearance.fish index 089329a..8e2e6c2 100644 --- a/private_dot_config/private_fish/private_tests/private_test_tide_terminal_appearance.fish +++ b/private_dot_config/private_fish/private_tests/private_test_tide_terminal_appearance.fish @@ -33,17 +33,34 @@ end set -l light_mapper $project_root/functions/__tide_terminal_light_color.fish set -l appearance_applicator $project_root/functions/__tide_apply_terminal_appearance.fish +set -l luminance_helper $project_root/functions/__tide_relative_luminance.fish +set -l scale_helper $project_root/functions/__tide_scale_luminance.fish +set -l ceiling_helper $project_root/functions/__tide_contrast_ceiling.fish +set -l background_probe $project_root/functions/__tide_terminal_background_color.fish -test -f $light_mapper -or __test_fail "missing light palette mapper" -test -f $appearance_applicator -or __test_fail "missing terminal appearance applicator" +for file in $light_mapper $appearance_applicator $luminance_helper $scale_helper \ + $ceiling_helper $background_probe + test -f $file + or __test_fail "missing "(path basename $file) +end source $light_mapper +source $luminance_helper +source $scale_helper +source $ceiling_helper +source $background_probe source $appearance_applicator +# The applicator exports its overrides, so a shell that already applied a +# palette passes them to this one through the environment. Dropping the +# inherited globals makes every tide_* name resolve to its universal value +# again, which is the configured dark palette this suite is written against. +for name in (set --universal --names | string match -e -r '^tide_') + set --erase --global $name +end + __test_assert_equal E4E4E4 (__tide_terminal_light_color 303030) \ - "dark segment background maps to the light segment background" + "dark segment background maps to the reference light segment background" __test_assert_equal 006C9E (__tide_terminal_light_color 00AFFF) \ "bright blue maps to its contrast-safe light equivalent" __test_assert_equal CF0000 (__tide_terminal_light_color FF0000) \ @@ -51,13 +68,61 @@ __test_assert_equal CF0000 (__tide_terminal_light_color FF0000) \ __test_assert_equal glyph (__tide_terminal_light_color glyph) \ "non-color values are preserved" +set -l reference_luminance (__tide_relative_luminance E4E4E4) +test (math -s0 "round($reference_luminance * 1000)") -eq 776 +or __test_fail "relative luminance of E4E4E4: expected 0.776, got $reference_luminance" + +# Halving a color's luminance has to actually halve it, whatever its hue. +# Only the rounding back to 8 bits per channel is allowed to show up. +for color in EBE8E4 006C9E 7B6400 4C6C6C + set -l halved (__tide_scale_luminance $color 0.5) + set -l ratio (math (__tide_relative_luminance $halved)" / "(__tide_relative_luminance $color)) + set -l scaled (math -s0 "round($ratio * 1000)") + test $scaled -ge 490 -a $scaled -le 510 + or __test_fail "scaling $color by 0.5 moved luminance by $ratio, not 0.5" +end + +__test_assert_equal FFFFFF (__tide_scale_luminance 808080 100) \ + "scaling clamps channels at the top of the range" +__test_assert_equal 000000 (__tide_scale_luminance 808080 0) \ + "scaling clamps channels at the bottom of the range" +__tide_scale_luminance nothex 0.5 +__test_assert_equal 1 $status "scaling rejects values that are not colors" + +__test_assert_equal 0.116667 (__tide_contrast_ceiling 0.7 4.5) \ + "the contrast ceiling is the darkest partner a background can carry" +__test_assert_equal 0 (__tide_contrast_ceiling 0.1 4.5) \ + "an unreachable contrast ceiling clamps at zero" + +set -l fake_config (mktemp -d) +printf 'background #EBE8E4\n' >$fake_config/light-theme.auto.conf +# A light background under a dark appearance means the wrong file was read, so +# the probe has to skip it and keep looking. +printf 'background #FFFFFF\n' >$fake_config/dark-theme.auto.conf +printf 'background #101010\n' >$fake_config/no-preference-theme.auto.conf + +__test_assert_equal EBE8E4 \ + (KITTY_CONFIG_DIRECTORY=$fake_config __tide_terminal_background_color light) \ + "the probe reads the background kitty is showing" +__test_assert_equal 101010 \ + (KITTY_CONFIG_DIRECTORY=$fake_config __tide_terminal_background_color dark) \ + "the probe rejects a background that contradicts the appearance" + +set -l empty_config (mktemp -d) +KITTY_CONFIG_DIRECTORY=$empty_config __tide_terminal_background_color light +__test_assert_equal 1 $status "the probe reports failure when no theme is readable" + +rm -rf $fake_config $empty_config + set -l empty_palette_result ( fish --no-config -c ' - source $argv[1] - source $argv[2] - __tide_apply_terminal_appearance light + for file in $argv[2..] + source $file + end + __tide_apply_terminal_appearance light $argv[1] printf "status=%s" $status - ' $light_mapper $appearance_applicator 2>&1 | + ' EBE8E4 $light_mapper $luminance_helper $scale_helper $ceiling_helper \ + $background_probe $appearance_applicator 2>&1 | string collect ) __test_assert_equal status=2 $empty_palette_result \ @@ -77,19 +142,19 @@ or __test_fail "the test fixture has no Tide colors" set -l before_non_colors (string join \x1e (__test_snapshot no)) -__tide_apply_terminal_appearance light +__tide_apply_terminal_appearance light EBE8E4 __test_assert_equal 0 $status "light appearance applies successfully" -__test_assert_equal E4E4E4 $tide_pwd_bg_color \ - "light appearance replaces the existing prompt segment background" -__test_assert_equal 006C9E $tide_pwd_color_anchors \ - "light appearance replaces the existing prompt foreground" +__test_assert_equal DFDCD8 $tide_pwd_bg_color \ + "light appearance derives the segment background from the terminal background" +__test_assert_equal 006696 $tide_pwd_color_anchors \ + "light appearance shades foregrounds down to the derived segment background" set -l pwd_scope (set --show tide_pwd_bg_color | string collect) string match -q '*set in global scope, exported*' -- $pwd_scope or __test_fail "Tide overrides are not global and exported" set -l child_background (fish --no-config -c 'printf %s "$tide_pwd_bg_color"') -__test_assert_equal E4E4E4 $child_background \ +__test_assert_equal DFDCD8 $child_background \ "Tide renderer subprocess inherits the light background" set -l after_non_colors (string join \x1e (__test_snapshot no)) @@ -101,7 +166,7 @@ for name in $expected_color_names set --append first_light_state "$name="(string escape -- $$name) end -__tide_apply_terminal_appearance light +__tide_apply_terminal_appearance light EBE8E4 __test_assert_equal 1 $status "repeated light appearance is a no-op" set -l second_light_state @@ -112,14 +177,60 @@ __test_assert_equal (string join \x1e $first_light_state) \ (string join \x1e $second_light_state) \ "repeated light appearance preserves all color overrides" -begin - for index in (seq (count $expected_dark_colors)) - set -l dark (string upper -- $expected_dark_colors[$index]) - test "$dark" = 303030; and continue - printf '%s %s\n' $dark (__tide_terminal_light_color $dark) - end -end | node $project_root/tests/assert_tide_light_contrast.mjs -or __test_fail "light palette foreground contrast is below 4.5:1" +set --global __test_color_names $expected_color_names +set --global __test_dark_colors $expected_dark_colors +set --global __test_contrast_checker $project_root/tests/assert_tide_light_contrast.mjs + +function __test_assert_light_contrast --argument-names label + begin + for index in (seq (count $__test_color_names)) + set -l name $__test_color_names[$index] + set -l dark (string upper -- $__test_dark_colors[$index]) + test "$dark" = 303030; and continue + printf '%s %s\n' $dark (string upper -- $$name) + end + end | node $__test_contrast_checker $tide_pwd_bg_color + or __test_fail "light palette foreground contrast is below 4.5:1 on $label" +end + +__test_assert_light_contrast "a terminal-derived segment background" + +# A different terminal background is a different palette, not a repeat. +__tide_apply_terminal_appearance light nothex +__test_assert_equal 0 $status "a changed terminal background re-applies the palette" +__test_assert_equal F2F2F2 $tide_pwd_bg_color \ + "an unusable terminal background falls back to white" +__test_assert_light_contrast "the fallback segment background" + +__tide_apply_terminal_appearance light FFFFFF +__test_assert_equal 1 $status \ + "a background that resolves to the active one is still a no-op" + +__tide_apply_terminal_appearance light EBE8E4 +__test_assert_equal 0 $status "returning to the earlier background re-applies" +__test_assert_equal DFDCD8 $tide_pwd_bg_color \ + "returning to the earlier background restores its segment background" + +set --global __tide_terminal_segment_contrast 1.4 +set --global __tide_terminal_appearance '' +__tide_apply_terminal_appearance light EBE8E4 +__test_assert_equal C8C6C2 $tide_pwd_bg_color \ + "a configured segment contrast overrides the default step" +__test_assert_light_contrast "a configured segment contrast" + +# Anything that is not a ratio above 1:1 would make the segment vanish into the +# background or sit above it, so it is ignored rather than honoured. +for invalid in 0.8 1 nonsense '' + set --global __tide_terminal_segment_contrast $invalid + set --global __tide_terminal_appearance '' + __tide_apply_terminal_appearance light EBE8E4 + __test_assert_equal DFDCD8 $tide_pwd_bg_color \ + "a segment contrast of <$invalid> falls back to the default step" +end +set --erase __tide_terminal_segment_contrast + +set --global __tide_terminal_appearance '' +__tide_apply_terminal_appearance light EBE8E4 __tide_apply_terminal_appearance dark __test_assert_equal 0 $status "dark appearance applies successfully" diff --git a/private_dot_config/private_fish/private_tests/private_verify_tide_terminal_events.exp b/private_dot_config/private_fish/private_tests/private_verify_tide_terminal_events.exp index 698557c..853469a 100644 --- a/private_dot_config/private_fish/private_tests/private_verify_tide_terminal_events.exp +++ b/private_dot_config/private_fish/private_tests/private_verify_tide_terminal_events.exp @@ -3,15 +3,21 @@ set timeout 30 log_user 0 +# The segment background is derived from the theme kitty is showing, so the +# emulated terminal responses below and the theme files have to agree. These +# fixtures are the white/black the responses report. +set kitty_config [file join [file dirname [file normalize [info script]]] fixtures kitty] + set path_label "direct" set through_tmux 0 if {[llength $argv] > 0 && [lindex $argv 0] eq "tmux"} { set path_label "tmux" set through_tmux 1 - spawn env TERM=xterm-kitty tmux -L tide-appearance-test \ + spawn env TERM=xterm-kitty KITTY_CONFIG_DIRECTORY=$kitty_config \ + tmux -L tide-appearance-test \ -f "$env(HOME)/.tmux.conf" new-session fish --interactive } else { - spawn env TERM=xterm-kitty fish --interactive + spawn env TERM=xterm-kitty KITTY_CONFIG_DIRECTORY=$kitty_config fish --interactive } if {$through_tmux} { @@ -60,7 +66,7 @@ if {$through_tmux} { send -- "printf 'CHECK:%s:%s\\n' \$__tide_terminal_appearance \$tide_pwd_bg_color\r" expect { - -re {CHECK:light:E4E4E4} {} + -re {CHECK:light:F2F2F2} {} timeout { puts stderr "The initial light terminal background did not apply the light Tide palette" exit 1