.emacs.d / vendor / google-maps / google-maps-geocode.el

;;; google-maps-geocode.el --- Geocode address using Google Maps service

;; Copyright (C) 2010 Julien Danjou

;; Author: Julien Danjou <>
;; Keywords: comm

;; This file is NOT part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <>.

;;; Commentary:
;; None
;;; Code:
  (require 'cl))

(require 'json)
(require 'google-maps-base)

(defconst google-maps-geocode-uri
  "Google Maps Geocoding API server.")

(defun google-maps-geocode-build-url (plist)
  "Built a Google Maps Geocode API request URL from PLIST."
   google-maps-geocode-uri "?"
    '((address . url-hexify-string)
      ;; Sensor is MANDATORY
      (sensor . (lambda (v)
                  (if v "true" "false")))
      (bounds . (lambda (v)
                  (mapconcat 'identity v "|")))

(defun google-maps-geocode-request->status (data)
  "Return status of a `google-maps-geocode' request.
It should returned `ok' if everything went well."
  (intern (downcase (cdr (assoc 'status data)))))

(defun google-maps-geocode-request-is-ok (data)
  "Return t if the geocoding via `google-maps-geocode' went fine."
  (eq (google-maps-geocode-request->status data) 'ok))

(defun google-maps-geocode-request->results (data)
  "Return result list of a `google-maps-geocode' request."
  (cdr (assoc 'results data)))

(defun google-maps-geocode-request (&rest params)
  "Request geocoding of a location and return the request result.
Request status can be retrieved with
`google-maps-geocode-request->status'. Request results data can
be retrieve ed with `google-maps-geocode-request->results'.

Valid params are:

  :address  The address to geocode.
  :sensor   Boolean indicating if this call is used for a sensor
  :latlng   Coordinates.
  :region   Region.
  :bounds   Bounding box.
  :language Language to use in returned data."
     (google-maps-build-plist params)))))

(defun google-maps-geocode-results->one-result-picked-by-user (results)
  "Make the user choose a result from RESULTS, and return it."
  (let ((location
         ;; `location' will contains what the user choosed as location.
          "Precise location: "
           (lambda (x)
             (cdr (assoc 'formatted_address x)))
          nil t)))
    ;; Find entry with that location
     `(lambda (entry)
        (string= (cdr (assoc 'formatted_address entry))

(defun google-maps-geocode-results->one-result (results)
  "Converts geocoding results list to one result only.
If there is several results, the user is asked to pick one via
  (case (length results)
    (0 nil)
    (1 (elt results 0))
    (t (google-maps-geocode-results->one-result-picked-by-user results))))

(defun google-maps-geocode-location (location)
  (let* ((req (google-maps-geocode-request :address location))
         (status (google-maps-geocode-request->status req)))
    (unless (eq status 'ok)
      (error (format "Unable to geocode %s: %s" location status)))
     (google-maps-geocode-request->results req))))

(defun google-maps-geocode-location->coordinates (location)
  "Return a list containing latitude and longitude."
  (let ((geocode-location (google-maps-geocode-location location))
	latitude longitude)
    (if (null (assoc 'geometry geocode-location))
	(error (format "No geometry information for location: %s" location)))
    (setq latitude (cdr (assoc 'lat (assoc 'location (assoc 'geometry geocode-location)))))
    (setq longitude (cdr (assoc 'lng (assoc 'location (assoc 'geometry geocode-location)))))
    (if (or (null latitude) (null longitude))
	(error (format "Null location coordinates: %s,%s" latitude longitude)))
    (list latitude longitude)))

(defun google-maps-geocode-replace-region (beg end)
  "Geocode region and replace it with a more accurate result."
  (interactive "r")
  (let ((location (cdr (assoc 'formatted_address
                               (buffer-substring beg end))))))
    (delete-region beg end)
    (insert location)))

(provide 'google-maps-geocode)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.