Skip to content

Locations

Adam Mladý edited this page Oct 9, 2025 · 3 revisions

Introduction

These came about as it is a pain to set locations manually all the time.

The Locations file is in the same directory as config and it is in JSON format.

{
  "0": {
    "latitude": 40.71,
    "longitude": -74.01,
    "city": "New York",
    "country": "USA",
    "units": "imp",
    "default": false
  },
  "1": {
  ...
  },
  ...
}

It uses the same values as the config, other that ip location (since that is not needed here) and defaults.

Creating Locations File

Quite simple, simply echo "{}" to a json file.

  SAVE_PATH="$HOME/.config/wayweather/locations.json"
  if [ ! -f "$SAVE_PATH" ]; then
    printf "{}" >"$SAVE_PATH"
    echo "[LOG] Created Custom Locations File"
  fi

--set or Saving Locations

This is quite short. As saving locations uses the same arguments as setting locations, I added arguments to save it from the --set argument.

    --save              Save custom location for
                        future use. Use with all
                        setting arguments.
    --skip-config       Skip config generation
                        when saving custom location

The skip config skips config generation, when you only want to save, not refresh waybar to use the new location.

The locations are saved with default being false and ordered by number of locations.

  JSON="{\"$(cat "$SAVE_PATH" | jq length)\":{
\"latitude\":$LAT,
\"longitude\":$LONG,
\"city\":\"$CITY\",
\"country\":\"$COUNTRY\",
\"units\":\"$UNITS\",
\"default\":false
}}"

--load or Loading Locations

The loading of locations is done by listing them and selecting from the list.

    for index in $(seq 0 "$(($(echo "$JSON" | jq length) - 1))"); do
      UNITS="$(if [[ $(echo "$JSON" | jq ".[\"$index\"].units") == '"met"' ]]; then echo "°C, mm, km/h"; else echo "°F, inch, mph"; fi)"
      echo "[$index]\
$(if [[ "$(echo "$JSON" | jq ".[\"$index\"].default")" == "true" ]]; then echo "*"; else echo ""; fi) \
$(echo "$JSON" | jq ".[\"$index\"].city"), $(echo "$JSON" | jq ".[\"$index\"].country") \
($(echo "$JSON" | jq ".[\"$index\"].latitude"), $(echo "$JSON" | jq ".[\"$index\"].longitude")) \
[$UNITS]" | sed -e 's/"//g'
    done
    unset UNITS

    if [[ "$(echo "$JSON" | jq length)" -gt "1" ]]; then
      read -p "Enter a number [0-"$(($(echo "$JSON" | jq length) - 1))"]: " INPUT
      if ! [[ "$INPUT" =~ ^[0-9]+$ ]] || ! [[ "$INPUT" -ge "0" ]] || ! [[ "$INPUT" -le "$(($(echo "$JSON" | jq length) - 1))" ]]; then
        echo "[ERROR] Input Not a Valid Number! Exiting."
        exit 1
      fi
      echo "[LOG] Selecting Locations number $INPUT"
    elif [[ "$(echo "$JSON" | jq length)" -eq "0" ]]; then
      echo "[ERROR] No Locations Saved! Exiting."
      exit 1
    else
      echo "[LOG] Selecting Location number 0"
    fi

This results in a list like:

[0]* New York, USA (40.71, -74.01) [°F, inch, mph]
[1] ...
...
[N]
Enter a Number [0-N]: 

Stars next to numbers mean the location is set as default.

Defaults can be loaded faster via --load default and they bypass this selection system.

--set-default or Setting Default Location

Uses the same code as --load, just inserts DEFAULT="$(if [[ "$(echo "$JSON" | jq ".[\"$index\"].default")" == "true" ]]; then echo "$index"; else echo "$DEFAULT"; fi)" into the for loop.

Then you select the one you want default and it checks.

  if [[ "$INPUT" == "$DEFAULT" ]]; then
    echo "[LOG] Selected Location is already Default"
    echo "[LOG] Exiting"
    exit 0
  else
    if [[ "$DEFAULT" == "" ]]; then
      MOD="$(echo "$JSON" | jq ".[\"$INPUT\"].default = true")"
      echo "$MOD" >"$SAVE_PATH"
      echo "[LOG] Default Location Selected"
    else
      MOD="$(echo "$JSON" | jq ".[\"$INPUT\"].default = true" | jq ".[\"$DEFAULT\"].default = false")"
      echo "$MOD" >"$SAVE_PATH"
      echo "[LOG] Default Location Selected"
    fi
  fi

--delete or Deleting Locations

> wayweather [-d/--delete] [OPTIONS]

OPTIONS:
  -y, --yes       Auto confirms deletion of a
                  location
  ID              Expects a location ID from --list
                  Will delete specific location

Deletes saved locations via either an argument (ID)
or via a selection.
By default, deleting requires a confirmation (Y/n).
Adding argument --yes skips the confirmation and
auto accepts it.

It has a confirmation for UX but can be overriden. You can also input a location ID for deleting without interaction.

When deleting, if the selected ID is the last, it just deletes it. But if the ID is anything else, it goes through the rest of the ID's and moves them in the JSON so that the ID's do not have a missing ID between them.

      DELETE="$(echo "$JSON" | jq "del(.[\"$LOCATION_ID\"])")"
      for id in $(seq "$((LOCATION_ID + 1))" "$(($(echo "$JSON" | jq length) - 1))"); do
        DELETE="$(echo "$DELETE" | jq -S ". += {\"$((id - 1))\": $(echo "$DELETE" | jq -c ".[\"$id\"]")}")"
        DELETE="$(echo "$DELETE" | jq "del(.[\"$id\"])")"

Clone this wiki locally