Emacs Lisp: Command to Change Earth-Coordinate to Google Map Link
This page shows a emacs command to turn earth coordinate into Google Map link.
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'll be changed into a Google Map link, like this:
<a href="http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333" title="�">Google Map</a>
Solution
Here's the emacs lisp command to do it.
(defun xah-google-map-linkify () "Change coordinate under cursor into a Google Map link. The current line must be one of the following format: 40°42′46″N 74°00′21″W 40.71277777777778 -74.00583333333333 The above is ‹latitude› ‹longitude› (That's New York City) (Note: latitude is y-axis, longitude is x-axis) If there's a text selection, use that as input. Sample result: <a href=\"http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333\" title=\"▮\">Google Map</a> URL `http://xahlee.info/emacs/emacs/elisp_make_google-map_link.html' Version 2016-07-12 2021-05-02" (interactive) (let ($p1 $p2 $input $coord-x $coord-y $coord-y-x ) (if (use-region-p) (setq $p1 (region-beginning) $p2 (region-end)) (setq $p1 (line-beginning-position) $p2 (line-end-position))) (setq $input (buffer-substring-no-properties $p1 $p2)) (if (string-match-p "°" $input) (progn (setq $coord-y-x (xah-latitude-longitude-decimalize $input)) (setq $coord-y (aref $coord-y-x 0)) (setq $coord-x (aref $coord-y-x 1))) (progn (let ( ($xx (split-string $input " " "OMIT-NULLS"))) (setq $coord-y (string-to-number (nth 0 $xx))) (setq $coord-x (string-to-number (nth 1 $xx))) (setq $coord-y-x (vector $coord-y $coord-x))))) (delete-region $p1 $p2) (xah-insert-google-map-link "▮" $coord-y-x)))
Alt+x xah-google-map-linkify
The following two functions are required.
(defun xah-insert-google-map-link (&optional @title @latlon) "Insert HTML link to Google Map. @title is the title attribute for the HTML link. @latlon is a vector [y x] where y is latitude, x is longitude. Each must be a decimal number. See also: `xah-latitude-longitude-decimalize' Example of inserted text: <a href=\"http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333\" title=\"▮\">Google Map</a> URL `http://xahlee.info/emacs/emacs/elisp_make_google-map_link.html' Version 2015-05-12 2021-05-02" (interactive) (let ($title $y $x) (setq $title (if @title @title "")) (if @latlon (progn (setq $y (elt @latlon 0)) (setq $x (elt @latlon 1))) (progn (setq $y "y▮") (setq $x "x▮"))) (insert "<a href=\"http://maps.google.com/maps?q=" (number-to-string $y) "%2C" (number-to-string $x) "\" title=\"" $title "\">Google Map</a>\n")))
(defun xah-latitude-longitude-decimalize (@latlon) "Convert latitude longitude string *latlon in minutes second format to decimal. Returns a vector. For example: 「\"37°26′36.42″N 06°15′14.28″W\"」 becomes 「[37.44345 -6.253966666666667]」 (Note: latitude is “horizontal lines”, longitude is “vertical lines”) URL `http://xahlee.info/emacs/emacs/elisp_make_google-map_link.html' Version 2015-02-08" (interactive) (let (($tmpPair (split-string (replace-regexp-in-string "'" "′" (replace-regexp-in-string "\"" "″" (replace-regexp-in-string "''" "″" @latlon t t) t t) t t) " +")) $latStr $latNum $lonStr $lonNum $deg $min $sec $sign ($c (/ 1.0 60.0))) (when (not (equal (length $tmpPair) 2)) (user-error "Error: input can contain only one space")) (setq $latStr (elt $tmpPair 0)) (setq $lonStr (elt $tmpPair 1)) (if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" $latStr ) (progn (setq $deg (string-to-number (match-string 1 $latStr))) (setq $min (string-to-number (match-string 2 $latStr))) (setq $sec (string-to-number (match-string 3 $latStr))) (setq $sign (match-string 4 $latStr)) (setq $latNum (+ $deg (* (+ $min (* $sec $c)) $c))) (cond ((string-equal (downcase $sign) "n") nil) ((string-equal $sign "") nil) ((string-equal (downcase $sign) "s") (setq $latNum (* -1 $latNum))) (t (user-error "Your input is malformed. Your latitude ends with a char that's not N or S")))) (progn (user-error "Your latitude is malformed"))) (if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" $lonStr ) (progn (setq $deg (string-to-number (match-string 1 $lonStr))) (setq $min (string-to-number (match-string 2 $lonStr))) (setq $sec (string-to-number (match-string 3 $lonStr))) (setq $sign (match-string 4 $lonStr)) (setq $lonNum (+ $deg (* (+ $min (* $sec $c)) $c))) (cond ((string-equal (downcase $sign) "e") nil) ((string-equal $sign "") nil) ((string-equal (downcase $sign) "w") (setq $lonNum (* -1 $lonNum))) (t (user-error "Your input is malformed. Your longitude ends with a char that's not E or W")))) (progn (user-error "Your longitude is malformed"))) (vector $latNum $lonNum)))