By Xah Lee. Date: . Last updated: .

Problem

Suppose you have a earth coordinate under cursor, like this:

`40°42′46″N 74°00′21″W`

or

`40.71277777777778 -74.00583333333333`

Press a button, and it becomes a Google Map link, like this:

```<a class="ggMap" href="http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333">Location</a>
```

Solution

Here's the emacs lisp command to do it.

Alt+x `xah-google-map-linkify`

put this in your Emacs Init File:

```;; -*- coding: utf-8; lexical-binding: t; -*-

(defun xah-latitude-longitude-decimalize (CoordYX)
"Convert latitude longitude string CoordYX in minutes second format to decimal.
Return a vector.
For example, string
37°26′36.42″N 06°15′14.28″W
becomes
[37.44345 -6.253966666666667]

Version: 2015-02-08 2023-07-23"
(let ((xtmpPair
(split-string
(replace-regexp-in-string
"'" "′"
(replace-regexp-in-string
"\"" "″"
(replace-regexp-in-string "''" "″" CoordYX t t) t t) t t)
" +"))
xlatStr xlatNum xlonStr xlonNum xdeg xmin xsec xsign (xc (/ 1.0 60.0)))
(when (not (equal (length xtmpPair) 2)) (user-error "Error: input can contain only one space"))
(setq xlatStr (elt xtmpPair 0) xlonStr (elt xtmpPair 1))
(if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" xlatStr)
(progn
(setq xdeg (string-to-number (match-string 1 xlatStr)))
(setq xmin (string-to-number (match-string 2 xlatStr)))
(setq xsec (string-to-number (match-string 3 xlatStr)))
(setq xsign (match-string 4 xlatStr))
(setq xlatNum (+ xdeg (* (+ xmin (* xsec xc)) xc)))
(cond
((string-equal (downcase xsign) "n") nil)
((string-equal xsign "") nil)
((string-equal (downcase xsign) "s") (setq xlatNum (* -1 xlatNum)))
(t (user-error "Input is malformed. Your latitude ends with a char that's not N or S"))))
(progn (user-error "Latitude is malformed")))

(if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" xlonStr)
(progn
(setq xdeg (string-to-number (match-string 1 xlonStr)))
(setq xmin (string-to-number (match-string 2 xlonStr)))
(setq xsec (string-to-number (match-string 3 xlonStr)))
(setq xsign (match-string 4 xlonStr))
(setq xlonNum (+ xdeg (* (+ xmin (* xsec xc)) xc)))
(cond
((string-equal (downcase xsign) "e") nil)
((string-equal xsign "") nil)
((string-equal (downcase xsign) "w") (setq xlonNum (* -1 xlonNum)))
(t (user-error "Input is malformed. Your longitude ends with a char that's not E or W"))))
(progn (user-error "Longitude is malformed")))
(vector xlatNum xlonNum)))

Title is the title attribute for the HTML link.
CoordYX is a vector [y x] where y is latitude, x is longitude. Each must be a decimal number.

Sample output:

Version: 2015-05-12 2021-05-02 2022-01-27"
(let (xtitle xy xx)
(setq xtitle (if Title Title ""))
(if CoordYX
(setq xy (elt CoordYX 0) xx (elt CoordYX 1))
(setq xy "y▮" xx "x▮"))
;; (insert "<a href=\"http://maps.google.com/maps?q=" (number-to-string xy) "%2C" (number-to-string xx) "\" title=\"" xtitle "\">Google Map</a>\n")
(format
(number-to-string xy)
"%2C"
(number-to-string xx)
xtitle
)))

If there's a text selection, use that as input.

The current line must be one of the following format:

40°42′46″N 74°00′21″W
40.71277777777778 -74.00583333333333

(New York City coordinate.)

Note, by convention, earth coordinates are given in this order:
‹latitude› ‹longitude›
(latitude is like  y axis, longitude is like x axis)

Sample result:

Version: 2016-07-12 2022-01-27 2023-07-23"
(interactive)
(let (xp1 xp2 xinput xcoord-x xcoord-y xcoord-y-x)
(if (use-region-p)
(setq xp1 (region-beginning) xp2 (region-end))
(setq xp1 (line-beginning-position) xp2 (line-end-position)))

(setq xinput (buffer-substring-no-properties xp1 xp2))
(if (string-match-p "°" xinput)
(progn
(setq xcoord-y-x (xah-latitude-longitude-decimalize xinput)
xcoord-y (aref xcoord-y-x 0)
xcoord-x (aref xcoord-y-x 1)))
(progn
(let ((xxx (split-string xinput  " " "OMIT-NULLS")))
(setq xcoord-y (string-to-number (nth 0 xxx))
xcoord-x (string-to-number (nth 1 xxx))
xcoord-y-x (vector xcoord-y xcoord-x)))))
(delete-region xp1 xp2)