-
Notifications
You must be signed in to change notification settings - Fork 519
Modified the Weather segment script to be less complicated #468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
erikw
merged 1 commit into
erikw:main
from
onlyuuuuu:refactor/465/less-complicated-weather-script-updates
Apr 30, 2025
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,51 +3,64 @@ | |
# To configure your location, set TMUX_POWERLINE_SEG_WEATHER_LOCATION in the tmux-powerline config file. | ||
|
||
TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT="yrno" | ||
TMUX_POWERLINE_SEG_WEATHER_JSON_DEFAULT="jq" | ||
TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT="c" | ||
TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT="600" | ||
|
||
if shell_is_bsd && [ -f /user/local/bin/grep ]; then | ||
TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT="/usr/local/bin/grep" | ||
else | ||
TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT="grep" | ||
fi | ||
TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT="86400" # 24 hours | ||
TMUX_POWERLINE_SEG_WEATHER_LAT_DEFAULT="auto" | ||
TMUX_POWERLINE_SEG_WEATHER_LON_DEFAULT="auto" | ||
|
||
generate_segmentrc() { | ||
read -r -d '' rccontents <<EORC | ||
# The data provider to use. Currently only "yahoo" is supported. | ||
# The data provider to use. Currently only "yrno" is supported. | ||
export TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER="${TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT}" | ||
# What unit to use. Can be any of {c,f,k}. | ||
export TMUX_POWERLINE_SEG_WEATHER_UNIT="${TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT}" | ||
# How often to update the weather in seconds. | ||
export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT}" | ||
# Name of GNU grep binary if in PATH, or path to it. | ||
export TMUX_POWERLINE_SEG_WEATHER_GREP="${TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT}" | ||
# Location of the JSON parser, jq | ||
export TMUX_POWERLINE_SEG_WEATHER_JSON="${TMUX_POWERLINE_SEG_WEATHER_JSON_DEFAULT}" | ||
# How often to update the weather location in seconds (this is only used when latitude and longitude settings are set to "auto") | ||
export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT}" | ||
# Your location | ||
# Latitude and Longtitude for use with yr.no | ||
# Set both to "auto" to detect automatically based on your IP address | ||
TMUX_POWERLINE_SEG_WEATHER_LAT="" | ||
TMUX_POWERLINE_SEG_WEATHER_LON="" | ||
# Set both to "auto" to detect automatically based on your IP address, or set them manually | ||
export TMUX_POWERLINE_SEG_WEATHER_LAT="${TMUX_POWERLINE_SEG_WEATHER_LAT_DEFAULT}" | ||
export TMUX_POWERLINE_SEG_WEATHER_LON="${TMUX_POWERLINE_SEG_WEATHER_LON_DEFAULT}" | ||
EORC | ||
echo "$rccontents" | ||
} | ||
|
||
run_segment() { | ||
__process_settings | ||
local tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/temp_weather_file.txt" | ||
local weather | ||
case "$TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER" in | ||
"yrno") weather=$(__yrno) ;; | ||
*) | ||
echo "Unknown weather provider [$TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER]" | ||
return 1 | ||
;; | ||
esac | ||
if [ -n "$weather" ]; then | ||
echo "$weather" | ||
local cache_weather_file="${TMUX_POWERLINE_DIR_TEMPORARY}/weather_cache_data.txt" | ||
local cache_location_file="${TMUX_POWERLINE_DIR_TEMPORARY}/weather_cache_location.txt" | ||
local weather="" | ||
|
||
# Check if the weather data is still a valid cache hit | ||
if [ -f "$cache_weather_file" ]; then | ||
last_update=$(__read_file_last_update "$cache_weather_file") | ||
time_now=$(date +%s) | ||
up_to_date=$(echo "(${time_now}-${last_update}) < ${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD}" | bc) | ||
if [ "$up_to_date" -eq 1 ]; then | ||
weather=$(__read_file_content "$cache_weather_file") | ||
fi | ||
fi | ||
|
||
# Fetch from provider if empty | ||
# If a new provider is implemented, please set the $weather variable! | ||
if [ -z "$weather" ]; then | ||
__process_settings | ||
case "$TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER" in | ||
"yrno") | ||
weather=$(__yrno) | ||
;; | ||
*) | ||
# Just read the stale cache, default to empty/blank | ||
# Better not overwriting the previous healthy content | ||
weather=$(__read_file_content "$cache_weather_file") | ||
;; | ||
esac | ||
echo "$weather" > "$cache_weather_file" | ||
fi | ||
|
||
echo "$weather" | ||
} | ||
|
||
__process_settings() { | ||
|
@@ -60,66 +73,52 @@ __process_settings() { | |
if [ -z "$TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD" ]; then | ||
export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT}" | ||
fi | ||
if [ -z "$TMUX_POWERLINE_SEG_WEATHER_GREP" ]; then | ||
export TMUX_POWERLINE_SEG_WEATHER_GREP="${TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT}" | ||
fi | ||
if [ -z "$TMUX_POWERLINE_SEG_WEATHER_JSON" ]; then | ||
export TMUX_POWERLINE_SEG_WEATHER_JSON="${TMUX_POWERLINE_SEG_WEATHER_JSON_DEFAULT}" | ||
if [ -z "$TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD" ]; then | ||
export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT}" | ||
fi | ||
if [ "$TMUX_POWERLINE_SEG_WEATHER_LAT" = "auto" ] || [ "$TMUX_POWERLINE_SEG_WEATHER_LON" = "auto" ]; then | ||
if [ "$TMUX_POWERLINE_SEG_WEATHER_LAT" = "auto" ] || [ "$TMUX_POWERLINE_SEG_WEATHER_LON" = "auto" ] || [ -z "$TMUX_POWERLINE_SEG_WEATHER_LON" ] || [ -z "$TMUX_POWERLINE_SEG_WEATHER_LAT" ]; then | ||
if ! get_auto_location; then | ||
exit 8 | ||
fi | ||
elif [ -z "$TMUX_POWERLINE_SEG_WEATHER_LON" ] || [ -z "$TMUX_POWERLINE_SEG_WEATHER_LAT" ]; then | ||
echo "No location defined." >&2 | ||
exit 8 | ||
fi | ||
} | ||
|
||
# An implementation of a weather provider, just need to echo the result, run_segment() will take care of the rest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea to add a note. Thanks! |
||
__yrno() { | ||
degree="" | ||
if [ -f "$tmp_file" ]; then | ||
if shell_is_macos || shell_is_bsd; then | ||
last_update=$(stat -f "%m" "${tmp_file}") | ||
elif shell_is_linux; then | ||
last_update=$(stat -c "%Y" "${tmp_file}") | ||
fi | ||
time_now=$(date +%s) | ||
local degree="" | ||
|
||
up_to_date=$(echo "(${time_now}-${last_update}) < ${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD}" | bc) | ||
if [ "$up_to_date" -eq 1 ]; then | ||
__read_tmp_file | ||
# There's a chance that you will get rate limited or both location APIs are not working | ||
# Then long and lat will be "null", as literal string | ||
if [ -z "$TMUX_POWERLINE_SEG_WEATHER_LAT" ] || [ -z "$TMUX_POWERLINE_SEG_WEATHER_LON" ]; then | ||
echo "Err: Unable to auto-detect your location" | ||
return 1 | ||
fi | ||
|
||
if weather_data=$(curl --max-time 4 -s "https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${TMUX_POWERLINE_SEG_WEATHER_LAT}&lon=${TMUX_POWERLINE_SEG_WEATHER_LON}"); then | ||
error=$(echo "$weather_data" | grep -i "error") | ||
if [ -n "$error" ]; then | ||
echo "error" | ||
return 1 | ||
fi | ||
degree=$(echo "$weather_data" | jq -r '.properties.timeseries | .[0].data.instant.details.air_temperature') | ||
condition=$(echo "$weather_data" | jq -r '.properties.timeseries | .[0].data.next_1_hours.summary.symbol_code') | ||
fi | ||
|
||
if [ -z "$degree" ]; then | ||
if weather_data=$(curl --max-time 4 -s "https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${TMUX_POWERLINE_SEG_WEATHER_LAT}&lon=${TMUX_POWERLINE_SEG_WEATHER_LON}"); then | ||
grep=$TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT | ||
error=$(echo "$weather_data" | $grep -i "error") | ||
if [ -n "$error" ]; then | ||
echo "error" | ||
exit 1 | ||
fi | ||
|
||
jsonparser="${TMUX_POWERLINE_SEG_WEATHER_JSON}" | ||
degree=$(echo "$weather_data" | $jsonparser -r '.properties.timeseries | .[0].data.instant.details.air_temperature') | ||
condition=$(echo "$weather_data" | $jsonparser -r '.properties.timeseries | .[0].data.next_1_hours.summary.symbol_code') | ||
elif [ -f "${tmp_file}" ]; then | ||
__read_tmp_file | ||
fi | ||
echo "yr.no err: unable to fetch weather data" | ||
return 1 | ||
fi | ||
|
||
if [ -n "$degree" ]; then | ||
if [ "$TMUX_POWERLINE_SEG_WEATHER_UNIT" == "k" ]; then | ||
degree=$(echo "${degree} + 273.15" | bc) | ||
fi | ||
if [ "$TMUX_POWERLINE_SEG_WEATHER_UNIT" == "f" ]; then | ||
degree=$(echo "${degree} * 9 / 5 + 32" | bc) | ||
fi | ||
# condition_symbol=$(__get_yrno_condition_symbol "$condition" "$sunrise" "$sunset") | ||
condition_symbol=$(__get_yrno_condition_symbol "$condition") | ||
echo "${condition_symbol} ${degree}°$(echo "$TMUX_POWERLINE_SEG_WEATHER_UNIT" | tr '[:lower:]' '[:upper:]')" | tee "${tmp_file}" | ||
if [ "$TMUX_POWERLINE_SEG_WEATHER_UNIT" == "k" ]; then | ||
degree=$(echo "${degree} + 273.15" | bc) | ||
fi | ||
if [ "$TMUX_POWERLINE_SEG_WEATHER_UNIT" == "f" ]; then | ||
degree=$(echo "${degree} * 9 / 5 + 32" | bc) | ||
fi | ||
# condition_symbol=$(__get_yrno_condition_symbol "$condition" "$sunrise" "$sunset") | ||
condition_symbol=$(__get_yrno_condition_symbol "$condition") | ||
# Write the <content@date>, separated by a @ character, so we can fetch it later on without having to call 'stat' | ||
echo "${condition_symbol} ${degree}°$(echo "$TMUX_POWERLINE_SEG_WEATHER_UNIT" | tr '[:lower:]' '[:upper:]')@$(date +%s)" | ||
} | ||
|
||
# Get symbol for condition. Available symbol names: https://api.met.no/weatherapi/weathericon/2.0/documentation#List_of_symbols | ||
|
@@ -177,23 +176,43 @@ __get_yrno_condition_symbol() { | |
esac | ||
} | ||
|
||
__read_tmp_file() { | ||
if [ ! -f "$tmp_file" ]; then | ||
__read_file_split() { | ||
onlyuuuuu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
file_to_read="$1" | ||
lookup_index="$2" | ||
fallback_value="$3" | ||
if [ ! -f "$file_to_read" ]; then | ||
echo "$fallback_value" | ||
return | ||
fi | ||
local -a file_arr | ||
IFS='@' read -ra file_arr <<< "$(cat "$file_to_read")" | ||
if [ -z "${file_arr[$lookup_index]}" ]; then | ||
echo "$fallback_value" | ||
return | ||
fi | ||
cat "${tmp_file}" | ||
exit | ||
echo "${file_arr[$lookup_index]}" | ||
} | ||
|
||
# Default to empty/blank | ||
__read_file_content() { | ||
__read_file_split "$1" 0 "" | ||
} | ||
|
||
# Default to 0 | ||
__read_file_last_update() { | ||
__read_file_split "$1" 1 0 | ||
} | ||
|
||
get_auto_location() { | ||
local cache_file="${TMUX_POWERLINE_DIR_TEMPORARY}/weather_location_cache.txt" | ||
local max_cache_age=86400 # 24 hours | ||
local max_cache_age=$TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD | ||
local -a lat_lon_arr | ||
|
||
if [[ -f "$cache_file" ]]; then | ||
local cache_age=$(($(date +%s) - $(stat -c %Y "$cache_file" 2>/dev/null || echo 0))) | ||
if [[ -f "$cache_location_file" ]]; then | ||
local cache_age=$(($(date +%s) - $(__read_file_last_update "$cache_location_file"))) | ||
if (( cache_age < max_cache_age )); then | ||
TMUX_POWERLINE_SEG_WEATHER_LAT=$(grep -oP "(?<=TMUX_POWERLINE_SEG_WEATHER_LAT=')[^']*" "$cache_file") | ||
TMUX_POWERLINE_SEG_WEATHER_LON=$(grep -oP "(?<=TMUX_POWERLINE_SEG_WEATHER_LON=')[^']*" "$cache_file") | ||
IFS=' ' read -ra lat_lon_arr <<< "$(__read_file_content "$cache_location_file")" | ||
TMUX_POWERLINE_SEG_WEATHER_LAT=${lat_lon_arr[0]} | ||
TMUX_POWERLINE_SEG_WEATHER_LON=${lat_lon_arr[1]} | ||
if [[ -n "$TMUX_POWERLINE_SEG_WEATHER_LAT" && -n "$TMUX_POWERLINE_SEG_WEATHER_LON" ]]; then | ||
return 0 | ||
fi | ||
|
@@ -214,18 +233,26 @@ get_auto_location() { | |
TMUX_POWERLINE_SEG_WEATHER_LON="${loc[1]}" | ||
;; | ||
esac | ||
if [[ -n "$TMUX_POWERLINE_SEG_WEATHER_LAT" && -n "$TMUX_POWERLINE_SEG_WEATHER_LON" ]]; then | ||
mkdir -p "$(dirname "$cache_file")" | ||
echo "TMUX_POWERLINE_SEG_WEATHER_LAT='$TMUX_POWERLINE_SEG_WEATHER_LAT'" > "$cache_file" | ||
echo "TMUX_POWERLINE_SEG_WEATHER_LON='$TMUX_POWERLINE_SEG_WEATHER_LON'" >> "$cache_file" | ||
return 0 | ||
|
||
# There's no data, move on to the next API, just don't overwrite the previous location | ||
# Also, there's a case where lat/lon was set to "null" as a string, gotta handle it | ||
if [[ -z "$TMUX_POWERLINE_SEG_WEATHER_LAT" || | ||
-z "$TMUX_POWERLINE_SEG_WEATHER_LON" || | ||
"$TMUX_POWERLINE_SEG_WEATHER_LAT" == "null" || | ||
"$TMUX_POWERLINE_SEG_WEATHER_LON" == "null" ]]; then | ||
continue | ||
fi | ||
|
||
echo "$TMUX_POWERLINE_SEG_WEATHER_LAT $TMUX_POWERLINE_SEG_WEATHER_LON@$(date +%s)" > "$cache_location_file" | ||
return 0 | ||
fi | ||
done | ||
if [[ -f "$cache_file" ]]; then | ||
|
||
if [[ -f "$cache_location_file" ]]; then | ||
echo "Warning: Using stale location data (failed to refresh)" >&2 | ||
TMUX_POWERLINE_SEG_WEATHER_LAT=$(grep -oP "(?<=TMUX_POWERLINE_SEG_WEATHER_LAT=')[^']*" "$cache_file") | ||
TMUX_POWERLINE_SEG_WEATHER_LON=$(grep -oP "(?<=TMUX_POWERLINE_SEG_WEATHER_LON=')[^']*" "$cache_file") | ||
IFS=' ' read -ra lat_lon_arr <<< "$(__read_file_content "$cache_location_file")" | ||
TMUX_POWERLINE_SEG_WEATHER_LAT=${lat_lon_arr[0]} | ||
TMUX_POWERLINE_SEG_WEATHER_LON=${lat_lon_arr[1]} | ||
if [[ -n "$TMUX_POWERLINE_SEG_WEATHER_LAT" && -n "$TMUX_POWERLINE_SEG_WEATHER_LON" ]]; then | ||
return 0 | ||
fi | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondrful 👏 🥳 🎆 , now this is the only echo for all code paths. This is a fantastic simplication of this old messy segment. Well don @onlyuuuuu !