Files
website/content/blog/script-map.sh.html
2025-11-30 09:39:17 -08:00

66 lines
4.1 KiB
HTML

<article>
<header id="title-block-header">
<h1 class=title">Script - map.sh</h1>
<p class="date">2025-05-03 00:00:00 -08:00</p>
</header>
<p>I created <a href="/scripts/map.sh">a neat little Bash script</a> and I was so pleased with how the script turned out that I wanted to share it in a blog post, essentially providing the missing comments in the script. I got inspired from <a href="https://www.youtube.com/watch?v=hZGKibcKP5M">a recent video</a> by Films By Kris <sup>(Kris with a K)</sup>. The script will output an <a href="https://openstreetmap.org">OpenStreetMap</a> URL for any address provided.</p>
<p>The address is provided as a string, either piped into the script or all arguments are combined into a string. The string is sent as a query request to OpenStreetMaps, using their <a href="https://nominatim.org/">Nominatim</a> API. OpenStreetMaps will return JSON data about the address, which the script will use to construct a URL linking to a map for the address, returned as standard output. There is no validation check with the address provided, so non-addresses can be used, but the script will fail if the address provided does not return JSON data.</p>
<p><code>curl</code> and <code>jq</code> are required for the script, <code>curl</code> is used to send the query and <code>jq</code> is used to parse the JSON that is returned from OpenStreetMaps. The function below checks to see if the programs are installed and exits with an error when anything is missing, listing the missing programs.</p>
<pre>command_check() {
local MISSING=()
for cmd in "$@"; do
if ! command -v "$cmd" &gt;/dev/null 2&gt;&amp;1; then
MISSING+=("$cmd")
fi
done
if [[ ${#MISSING[*]} -gt 0 ]]; then
echo "Error: Missing required programs:" &gt;&amp;2
for cmd in "${MISSING[@]}"; do
echo " - $cmd" &gt;&amp;2
done
exit 1
fi
}
command_check curl jq</pre>
<p>The address can be provided as standard input, either piped or provided as an argument. There is no error checking to confirm the string provided in a valid address, the API will return no data which will cause the JSON validation check to fail and exit with an error. If no data is piped and no arguments are given, then the script will ask for an address with user input. The input is replaces spaces with the URL encoded form to help curl with the request.</p>
<pre>if [[ ! -t 0 ]]; then
QUERY="$(cat)"
elif [[ $# -gt 0 ]]; then
QUERY="$*"
else
printf "Create a map link for a location.\n"
printf "Address? "
read -r QUERY
fi
ENCODED_QUERY="${QUERY// /%20}"
LOCATION_JSON="$(curl -s "https://nominatim.openstreetmap.org/search?q=$ENCODED_QUERY&amp;limit=2&amp;format=json")"
if ! jq empty &lt;&lt;&lt;"$LOCATION_JSON" 2&gt;/dev/null; then
echo "Error: Something wrong, invalid JSON for location query." &gt;&apm;2
exit 1
fi</pre>
<p>The <code>coordinate</code> function is used to pull the latitude and longitude coordinates from the JSON data, which it assigns to variables that are ultimately used in the final OpenStreetMap URL for a map with a marker pointing to the location.</p></p>
<pre>coordinate() {
local COOR="$1"
local VALUE
VALUE="$(jq -r ".[0].$COOR" &lt;&lt;&lt;"$LOCATION_JSON")"
if [[ "$VALUE" =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then
echo "$VALUE"
else
echo "Error: Not a number" &gt;&amp;2
echo "Usage: $0 &lt;address&gt;" &gt;&amp;2
echo "Query was: $QUERY" &gt;&amp;2
echo "Encoded query was: $ENCODED_QUERY" &gt;&amp;2
echo "Location JSON was: $LOCATION_JSON" &gt;&amp;2
exit 1
fi
}
LAT="$(coordinate lat)"
LON="$(coordinate lon)"
echo "https://www.openstreetmap.org/?mlat=$LAT&amp;mlon=$LON#map=16/$LAT/$LON"</pre>
<p>This script can be plugged into different configurations. I created the following little function in my main menu script (which will be shared another day). This function will ask me for an address with rofi and then copies the URL to the clipboard, and asks to open it.</p>
<pre>URL="$(printf '' | rofi -dmenu -i -p "Address? " | map.sh)"
wl-copy "$URL"
notify-send "copied" "$URL"
test "$(printf "Yes\nNo\n" | rofi -dmenu -i -p 'Open? ')" = "Yes" &amp;&amp; xdg-open "$URL"</pre>
</article>