Skip to content

Commit 14ed3dd

Browse files
authored
Merge pull request #515 from turtle11311/fix/weather-icon-style
feat(weather): add TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE option
2 parents 719b0d2 + 3f0c0d4 commit 14ed3dd

2 files changed

Lines changed: 100 additions & 43 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
9+
### Added
10+
- [`weather.sh`](segments/weather.sh): new `TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE` option (`emoji` / `emoji_fixed` / `nerdfonts` / `auto`) to control weather condition icon rendering. Fixes status-bar width miscounting caused by VS16 variation selectors on some terminals. Users experiencing the status-bar scrolling issue ([#351](https://github.com/erikw/tmux-powerline/issues/351)) should set `TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE="emoji_fixed"` or `"nerdfonts"`. After changing this option, delete `weather_cache_data.txt` in your tmux-powerline temp directory to see the effect immediately. [#515](https://github.com/erikw/tmux-powerline/pull/515)
911

1012
## [3.2.0] - 2026-02-04
1113
### Added

segments/weather.sh

Lines changed: 98 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT="600"
1313
TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT="86400" # 24 hours
1414
TMUX_POWERLINE_SEG_WEATHER_LAT_DEFAULT="auto"
1515
TMUX_POWERLINE_SEG_WEATHER_LON_DEFAULT="auto"
16+
# Icon style: "emoji" (default), "nerdfonts", "emoji_fixed", "auto"
17+
TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE_DEFAULT="emoji"
1618

1719
# Global cache file for weather data
1820
TMUX_POWERLINE_SEG_WEATHER_CACHE_FILE_WEATHER="${TMUX_POWERLINE_DIR_TEMPORARY}/weather_cache_data.txt"
@@ -35,6 +37,16 @@ export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_W
3537
# Set both to "auto" to detect automatically based on your IP address, or set them manually
3638
export TMUX_POWERLINE_SEG_WEATHER_LAT="${TMUX_POWERLINE_SEG_WEATHER_LAT_DEFAULT}"
3739
export TMUX_POWERLINE_SEG_WEATHER_LON="${TMUX_POWERLINE_SEG_WEATHER_LON_DEFAULT}"
40+
# Icon style for weather condition symbols:
41+
# "emoji" - emoji with VS16 variation selector (default, original behaviour)
42+
# "emoji_fixed" - emoji with VS16 stripped; fixes status-bar scrolling/duplication
43+
# on terminals that miscount VS16 width (see issue #351)
44+
# "nerdfonts" - Nerd Font PUA icons (1 cell, no width ambiguity); also fixes #351
45+
# if you already use a Nerd Font in your terminal
46+
# "auto" - nerdfonts when a patched font is detected, else emoji
47+
# Note: after changing this value, delete the weather cache file to see the effect immediately:
48+
# rm "${TMUX_POWERLINE_DIR_TEMPORARY}/weather_cache_data.txt"
49+
export TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE="${TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE_DEFAULT}"
3850
EORC
3951
echo "$rccontents"
4052
}
@@ -126,6 +138,12 @@ __process_basic_settings() {
126138
if [ -z "$TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD" ]; then
127139
export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT}"
128140
fi
141+
# Resolve icon style, including "auto" detection.
142+
local icon_style="${TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE:-$TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE_DEFAULT}"
143+
if [ "$icon_style" = "auto" ]; then
144+
tp_patched_font_in_use && icon_style="nerdfonts" || icon_style="emoji"
145+
fi
146+
export TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE="$icon_style"
129147
}
130148

131149

@@ -187,7 +205,7 @@ __yrno() {
187205
fi
188206
# condition_symbol=$(__get_yrno_condition_symbol "$condition" "$sunrise" "$sunset")
189207
local condition_symbol
190-
condition_symbol=$(__get_yrno_condition_symbol "$condition")
208+
condition_symbol=$(__get_yrno_condition_symbol "$condition" "${TMUX_POWERLINE_SEG_WEATHER_ICON_STYLE:-emoji}")
191209
# Write the <content@date>, separated by a @ character, so we can fetch it later on without having to call 'stat'
192210
echo "${condition_symbol} ${degree}°$(echo "$TMUX_POWERLINE_SEG_WEATHER_UNIT" | tr '[:lower:]' '[:upper:]')"
193211
}
@@ -208,56 +226,93 @@ __degree_c2f() {
208226

209227

210228
# Get symbol for condition. Available symbol names: https://api.met.no/weatherapi/weathericon/2.0/documentation#List_of_symbols
229+
# NOTE: when adding new yr.no condition codes, update all three tables below (nerdfonts, emoji_fixed, emoji).
211230
__get_yrno_condition_symbol() {
212231
# local condition=$(echo "$1" | tr '[:upper:]' '[:lower:]')
213232
# local sunrise="$2"
214233
# local sunset="$3"
215234
local condition=$1
216-
case "$condition" in
217-
"clearsky_day")
218-
echo "☀️ "
219-
;;
220-
"clearsky_night")
221-
echo "🌙"
222-
;;
223-
"fair_day")
224-
echo "🌤 "
225-
;;
226-
"fair_night")
227-
echo "🌜"
228-
;;
229-
"fog")
230-
echo "🌫 "
231-
;;
232-
"cloudy")
233-
echo "☁️ "
234-
;;
235-
"rain" | "lightrain" | "heavyrain" | "sleet" | "lightsleet" | "heavysleet")
236-
echo "🌧 "
237-
;;
238-
"heavyrainandthunder" | "heavyrainshowersandthunder_day" | "heavyrainshowersandthunder_night" | "heavysleetandthunder" | "heavysleetshowersandthunder_day" | "heavysnowandthunder" | "heavysnowshowersandthunder_day" | "heavysnowshowersandthunder_night" | "lightrainandthunder" | "lightrainshowersandthunder_day" | "lightrainshowersandthunder_night" | "lightsleetandthunder" | "lightsnowandthunder" | "lightssleetshowersandthunder_day" | "lightssleetshowersandthunder_night" | "lightssnowshowersandthunder_day" | "lightssnowshowersandthunder_night" | "rainandthunder" | "rainshowersandthunder_day" | "rainshowersandthunder_night" | "sleetandthunder" | "sleetshowersandthunder_day" | "sleetshowersandthunder_night" | "snowandthunder" | "snowshowersandthunder_day" | "snowshowersandthunder_night")
239-
echo "⛈️ "
240-
;;
241-
"heavyrainshowers_day" | "heavysleetshowers_day" | "heavysleetshowersandthunder_night" | "lightrainshowers_day" | "lightsleetshowers_day" | "rainshowers_day" | "sleetshowers_day")
242-
echo "🌦️ "
243-
;;
244-
"heavyrainshowers_night" | "heavysleetshowers_night" | "lightrainshowers_night" | "lightsleetshowers_night" | "rainshowers_night" | "sleetshowers_night")
245-
echo ""
246-
;;
247-
"snow" | "lightsnow" | "heavysnow")
248-
echo "❄️ "
249-
;;
250-
"lightsnowshowers_day" | "lightsnowshowers_night" | "heavysnowshowers_day" | "heavysnowshowers_night" | "snowshowers_day" | "snowshowers_night")
251-
echo "🌨 "
252-
;;
253-
"partlycloudy_day")
254-
echo ""
235+
local style="${2:-emoji}"
236+
237+
case "$style" in
238+
"nerdfonts")
239+
# Literal UTF-8 glyphs (MDI PUA, 1 cell, no width ambiguity). Bash 3.2-safe.
240+
case "$condition" in
241+
"clearsky_day") echo "󰖙 " ;; # U+F0599 mdi-weather-sunny
242+
"clearsky_night") echo "󰖔 " ;; # U+F0594 mdi-weather-night
243+
"fair_day") echo "󰖕 " ;; # U+F0595 mdi-weather-partly-cloudy
244+
"fair_night") echo "󰼱 " ;; # U+F0F31 mdi-weather-night-partly-cloudy
245+
"fog") echo "󰖑 " ;; # U+F0591 mdi-weather-fog
246+
"cloudy") echo "󰖐 " ;; # U+F0590 mdi-weather-cloudy
247+
"rain" | "lightrain" | "heavyrain" | "sleet" | "lightsleet" | "heavysleet")
248+
echo "󰖗 " ;; # U+F0597 mdi-weather-rainy
249+
"heavyrainandthunder" | "heavyrainshowersandthunder_day" | "heavyrainshowersandthunder_night" | "heavysleetandthunder" | "heavysleetshowersandthunder_day" | "heavysleetshowersandthunder_night" | "heavysnowandthunder" | "heavysnowshowersandthunder_day" | "heavysnowshowersandthunder_night" | "lightrainandthunder" | "lightrainshowersandthunder_day" | "lightrainshowersandthunder_night" | "lightsleetandthunder" | "lightsnowandthunder" | "lightsleetshowersandthunder_day" | "lightsleetshowersandthunder_night" | "lightsnowshowersandthunder_day" | "lightsnowshowersandthunder_night" | "rainandthunder" | "rainshowersandthunder_day" | "rainshowersandthunder_night" | "sleetandthunder" | "sleetshowersandthunder_day" | "sleetshowersandthunder_night" | "snowandthunder" | "snowshowersandthunder_day" | "snowshowersandthunder_night")
250+
echo "󰙾 " ;; # U+F067E mdi-weather-lightning-rainy
251+
"heavyrainshowers_day" | "heavysleetshowers_day" | "lightrainshowers_day" | "lightsleetshowers_day" | "rainshowers_day" | "sleetshowers_day")
252+
echo "󰼳 " ;; # U+F0F33 mdi-weather-partly-rainy
253+
"heavyrainshowers_night" | "heavysleetshowers_night" | "lightrainshowers_night" | "lightsleetshowers_night" | "rainshowers_night" | "sleetshowers_night")
254+
echo "󰖗 " ;; # U+F0597 mdi-weather-rainy
255+
"snow" | "lightsnow" | "heavysnow")
256+
echo "󰖘 " ;; # U+F0598 mdi-weather-snowy
257+
"lightsnowshowers_day" | "lightsnowshowers_night" | "heavysnowshowers_day" | "heavysnowshowers_night" | "snowshowers_day" | "snowshowers_night")
258+
echo "󰼴 " ;; # U+F0F34 mdi-weather-partly-snowy
259+
"partlycloudy_day") echo "󰖕 " ;; # U+F0595 mdi-weather-partly-cloudy
260+
"partlycloudy_night") echo "󰼱 " ;; # U+F0F31 mdi-weather-night-partly-cloudy
261+
*) echo "? " ;; # trailing space matches other nerdfonts entries
262+
esac
255263
;;
256-
"partlycloudy_night")
257-
echo "🌗"
264+
"emoji_fixed")
265+
# VS16 (U+FE0F) omitted from Neutral-width base characters (☀ ☁ ⛈ 🌦 ❄) so
266+
# tmux cell-width counting matches what the terminal renders. No sed needed.
267+
case "$condition" in
268+
"clearsky_day") echo "" ;;
269+
"clearsky_night") echo "🌙" ;;
270+
"fair_day") echo "🌤 " ;;
271+
"fair_night") echo "🌜" ;;
272+
"fog") echo "🌫 " ;;
273+
"cloudy") echo "" ;;
274+
"rain" | "lightrain" | "heavyrain" | "sleet" | "lightsleet" | "heavysleet")
275+
echo "🌧 " ;;
276+
"heavyrainandthunder" | "heavyrainshowersandthunder_day" | "heavyrainshowersandthunder_night" | "heavysleetandthunder" | "heavysleetshowersandthunder_day" | "heavysleetshowersandthunder_night" | "heavysnowandthunder" | "heavysnowshowersandthunder_day" | "heavysnowshowersandthunder_night" | "lightrainandthunder" | "lightrainshowersandthunder_day" | "lightrainshowersandthunder_night" | "lightsleetandthunder" | "lightsnowandthunder" | "lightsleetshowersandthunder_day" | "lightsleetshowersandthunder_night" | "lightsnowshowersandthunder_day" | "lightsnowshowersandthunder_night" | "rainandthunder" | "rainshowersandthunder_day" | "rainshowersandthunder_night" | "sleetandthunder" | "sleetshowersandthunder_day" | "sleetshowersandthunder_night" | "snowandthunder" | "snowshowersandthunder_day" | "snowshowersandthunder_night")
277+
echo "" ;;
278+
"heavyrainshowers_day" | "heavysleetshowers_day" | "lightrainshowers_day" | "lightsleetshowers_day" | "rainshowers_day" | "sleetshowers_day")
279+
echo "🌦 " ;;
280+
"heavyrainshowers_night" | "heavysleetshowers_night" | "lightrainshowers_night" | "lightsleetshowers_night" | "rainshowers_night" | "sleetshowers_night")
281+
echo "" ;;
282+
"snow" | "lightsnow" | "heavysnow")
283+
echo "" ;;
284+
"lightsnowshowers_day" | "lightsnowshowers_night" | "heavysnowshowers_day" | "heavysnowshowers_night" | "snowshowers_day" | "snowshowers_night")
285+
echo "🌨 " ;;
286+
"partlycloudy_day") echo "" ;;
287+
"partlycloudy_night") echo "🌗" ;;
288+
*) echo "? " ;;
289+
esac
258290
;;
259291
*)
260-
echo "?"
292+
# emoji: original symbols with VS16 variation selectors (default behaviour)
293+
case "$condition" in
294+
"clearsky_day") echo "☀️ " ;;
295+
"clearsky_night") echo "🌙" ;;
296+
"fair_day") echo "🌤 " ;;
297+
"fair_night") echo "🌜" ;;
298+
"fog") echo "🌫 " ;;
299+
"cloudy") echo "☁️ " ;;
300+
"rain" | "lightrain" | "heavyrain" | "sleet" | "lightsleet" | "heavysleet")
301+
echo "🌧 " ;;
302+
"heavyrainandthunder" | "heavyrainshowersandthunder_day" | "heavyrainshowersandthunder_night" | "heavysleetandthunder" | "heavysleetshowersandthunder_day" | "heavysleetshowersandthunder_night" | "heavysnowandthunder" | "heavysnowshowersandthunder_day" | "heavysnowshowersandthunder_night" | "lightrainandthunder" | "lightrainshowersandthunder_day" | "lightrainshowersandthunder_night" | "lightsleetandthunder" | "lightsnowandthunder" | "lightsleetshowersandthunder_day" | "lightsleetshowersandthunder_night" | "lightsnowshowersandthunder_day" | "lightsnowshowersandthunder_night" | "rainandthunder" | "rainshowersandthunder_day" | "rainshowersandthunder_night" | "sleetandthunder" | "sleetshowersandthunder_day" | "sleetshowersandthunder_night" | "snowandthunder" | "snowshowersandthunder_day" | "snowshowersandthunder_night")
303+
echo "⛈️ " ;;
304+
"heavyrainshowers_day" | "heavysleetshowers_day" | "lightrainshowers_day" | "lightsleetshowers_day" | "rainshowers_day" | "sleetshowers_day")
305+
echo "🌦️ " ;;
306+
"heavyrainshowers_night" | "heavysleetshowers_night" | "lightrainshowers_night" | "lightsleetshowers_night" | "rainshowers_night" | "sleetshowers_night")
307+
echo "" ;;
308+
"snow" | "lightsnow" | "heavysnow")
309+
echo "❄️ " ;;
310+
"lightsnowshowers_day" | "lightsnowshowers_night" | "heavysnowshowers_day" | "heavysnowshowers_night" | "snowshowers_day" | "snowshowers_night")
311+
echo "🌨 " ;;
312+
"partlycloudy_day") echo "" ;;
313+
"partlycloudy_night") echo "🌗" ;;
314+
*) echo "? " ;;
315+
esac
261316
;;
262317
esac
263318
}

0 commit comments

Comments
 (0)