diff --git a/CHANGELOG b/CHANGELOG index c3969f969ac2cf7956047bdc18fa6b0416f7e073..1342f911423685e6a18ebdd740902ef8612269d2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,18 @@ 2020-07-25 David Byers <david.byers@liu.se> + Fix issue #7: + * olc.texi: Fix documentation of olc-recover-compound, which was + plain wrong. Add documentation and examples for the "format" + keyword arg to olc-deocde. Update examples in olc-recover and + olc-recover-compound. Consistently format nil as code. + + * olc.el (olc-recover): Change from cons to list in latlon return + value. Will still only bump minor versions since there are no + users other than me. + (olc-is-valid): More flexible match for the separator after the + code. + (olc-decode): Added the "format" keyword arg. + Fix issue #6: * olc.texi (Functions): Document "compound". Correct error in documentation of return value for olc-is-full and olc-is-short. diff --git a/olc.el b/olc.el index f4a0fdfbc65ef0eee5f90f803d6a64ed866b63eb..422479012663a8f39964d72ff39d0127d47c44d0 100644 --- a/olc.el +++ b/olc.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2020 David Byers ;; ;; Author: David Byers <david.byers@liu.se> -;; Version: 1.3.0 +;; Version: 1.4.0 ;; Package-Requires: ((emacs "25.1")) ;; Keywords: extensions, lisp ;; URL: https://gitlab.liu.se/davby02/olc @@ -372,7 +372,7 @@ compound open location code (i.e. everything up to the first space character is a valid code)." (or (olc-parse-p code) (save-match-data - (when (and compound (string-match " " code)) + (when (and compound (string-match "\\s-+" code)) (setq code (substring code 0 (match-beginning 0)))) (let ((case-fold-search t)) @@ -491,7 +491,7 @@ raise an error." (apply #'string code))) -(defun olc-decode (code) +(cl-defun olc-decode (code &key (format 'area)) "Decode open location code CODE. Returns an `olc-area' structure. Raises `olc-parse-error' if the @@ -499,9 +499,16 @@ code can't be parsed, and `olc-decode-error' if it can't be decoded (e.g. a padded shortened code, a padded code with grid coordinates, an empty code, and so forth). +If FORMAT is `area' (the default), the returned value is an full +open location code. If FORMAT is `latlon' it is a list (LATITUDE +LONGITUDE) representing the center of the location. + Since this function uses floating point calculations, the results are not identical to e.g. the C++ reference implementation. The differences, however, are extremely small." + (cl-check-type code (or stringp olc-parse)) + (cl-check-type format (member latlon area)) + (let* ((parse (olc-parse-code code)) (latscale (* (expt 20 4) (expt 5 5))) (lonscale (* (expt 20 4) (expt 4 5))) @@ -534,10 +541,13 @@ differences, however, are extremely small." lon (+ lon (* lonsize (% coord 4)))))) (olc-parse-grid parse))) - (olc-area-create :latlo (/ lat (float latscale)) - :lonlo (/ lon (float lonscale)) - :lathi (/ (+ lat latsize) (float latscale)) - :lonhi (/ (+ lon lonsize) (float lonscale))))) + (if (eq format 'area) + (olc-area-create :latlo (/ lat (float latscale)) + :lonlo (/ lon (float lonscale)) + :lathi (/ (+ lat latsize) (float latscale)) + :lonhi (/ (+ lon lonsize) (float lonscale))) + (list (/ (+ lat (/ latsize 2)) (float latscale)) + (/ (+ lon (/ lonsize 2)) (float lonscale)))))) (cl-defun olc-shorten (code lat lon &key (limit 12)) @@ -678,11 +688,10 @@ faster. "Recover shortened code CODE from coordinates LAT and LON. Recovers the closest point to coordinates LAT and LON with a code -that can be shortened to CODE. If FORMAT is `latlon', then the -center of the recovered area (LATITUDE . LONGITUDE) is returned. - -If FORMAT is `area' (or any other value), the returned value is an -full open location code." +that can be shortened to CODE. If FORMAT is `area' (the default), +the returned value is an full open location code. If FORMAT is +`latlon' it is a list (LATITUDE LONGITUDE) representing the +center of the location." (cl-check-type code stringp) (cl-check-type lat number) (cl-check-type lon number) @@ -692,7 +701,7 @@ full open location code." (if (olc-is-full parse) (if (eq format 'latlon) (let ((area (olc-decode parse))) - (cons (olc-area-lat area) + (list (olc-area-lat area) (olc-area-lon area))) (upcase code)) (setq lat (olc-clip-latitude lat) @@ -719,7 +728,7 @@ full open location code." (setq lon (+ (olc-area-lon area) resolution))) (t (setq lon (olc-area-lon area)))) (if (eq format 'latlon) - (cons lat lon) + (list lat lon) (olc-encode lat lon :len (olc-parse-precision parse))))))) @@ -729,8 +738,9 @@ full open location code." Optional keyword argument REF indicates the reference to use. If not specified, the reference is assumed to be embedded into CODE. -If FORMAT is `area' (or any other value), the returned value is an -full open location code." +If FORMAT is `area' (the default), the returned value is an full +open location code. If FORMAT is `latlon' it is a list (LATITUDE +LONGITUDE) representing the center of the location." ;; Make sure we can do requests (save-match-data (unless (fboundp 'request) (signal 'void-function '(request))) diff --git a/olc.info b/olc.info index c7ef9ba2401e37a2e5f56c953312610f76bf2cb4..480e8a61ffd9348db97ea37231b682c60d435f89 100644 --- a/olc.info +++ b/olc.info @@ -229,12 +229,18 @@ Functions (e.g. a padded shortened code, a padded code with grid coordinates, an empty code, and so forth). + If FORMAT is ‘area’ (the default), the returned value is an full + open location code. If FORMAT is ‘latlon’ it is a list (LATITUDE + LONGITUDE) representing the center of the location. + (olc-decode "9FCQ9HXG+4CG") ⇒ #s(olc-area 58.397800000000004 15.5760625 58.397825000000005 15.57609375) (olc-area-lat (olc-decode "9FCQ9HXG+4CG")) ⇒ 58.3978125 (olc-area-lon (olc-decode "9FCQ9HXG+4CG")) ⇒ 15.576078125 + (olc-decode "9FCQ9HXG+4CG" :format 'latlon) + ⇒ (58.3978125 15.576078125) -- Function: olc-shorten code lat lon &key limit Shorten CODE, which must be a full open location code, using @@ -251,15 +257,15 @@ Functions -- Function: olc-shorten-compound code &key limit Shorten CODE, which must be a full open location code, finding a - reference near the encoded location. If LIMIT is non-nil, then the - code will be shortened by at most that many digits. If the code - can’t be shortened, the original code is returned. + reference near the encoded location. If LIMIT is non-‘nil’, then + the code will be shortened by at most that many digits. If the + code can’t be shortened, the original code is returned. - If ZOOM is non-nil, then limit references to that zoom level. The - default is 8 and the maximum is 18. Higher zoom levels yield more - precise but longer references. Lower zoom levels yield simpler - references but longer codes. The default seems to usually produce - codes with four characters before the plus sign. + If ZOOM is non-‘nil’, then limit references to that zoom level. + The default is 8 and the maximum is 18. Higher zoom levels yield + more precise but longer references. Lower zoom levels yield + simpler references but longer codes. The default seems to usually + produce codes with four characters before the plus sign. ‘olc-shorten-error’ is raised if CODE is a padded or shortened code, of if LIMIT is not even. @@ -277,35 +283,35 @@ Functions Recover the closest point to coordinates LAT and LON with a code that can be shortened to CODE. If FORMAT is ‘latlon’, then the center of the recovered area (LATITUDE . LONGITUDE) is returned. - If FORMAT is ‘area’ (or any other value), the returned value is an - full open location code. + + If FORMAT is ‘area’ (the default), the returned value is an full + open location code. If FORMAT is ‘latlon’ it is a list (LATITUDE + LONGITUDE) representing the center of the location. (olc-recover "+2VX" 51.3701125 -1.217765625) ⇒ "9C3W9QCJ+2VX" (olc-recover "+2VX" 51.3701125 -1.217765625 :format 'latlon) - ⇒ (51.370112500000005 . -1.2177656250000002) + ⇒ (51.370112500000005 -1.2177656250000002) - -- Function: olc-recover-compound arg1 &optional arg2 &key format + -- Function: olc-recover-compound code &key ref format Recover a shortened code without the reference latitude and longitude. - When called with one argument, it must be a string consisting of a - shortened open location code followed by whitespace and a - geographical location. - - When called with two strings, the first must be a shortened open - location code and the second if the geographical location. + CODE is the (shortened) code to decode. REF is either ‘nil’ or the + geographical reference to use instead of latitude and longitude. + If REF is ‘nil’, then CODE must end with the geographical + reference, separated from the code by whitespace. - Optionally, the last argument in either case can be a symbol - indicating the format of the return value (see ‘olc-recover’ for - details). + If FORMAT is ‘area’ (the default), the returned value is an full + open location code. If FORMAT is ‘latlon’ it is a list (LATITUDE + LONGITUDE) representing the center of the location. (olc-recover-compound "M24Q+89 Mutitjulu") ⇒ "5Q6HM24Q+89" (olc-recover-compound "M24Q+89" "Mutitjulu") ⇒ "5Q6HM24Q+89" (olc-recover-compound "M24Q+89" "Mutitjulu" :format 'latlon) - ⇒ (-25.344187500000004 . 131.0384375) + ⇒ (-25.344187500000004 131.0384375) This function requires the ‘request’ package to be installed, and uses the OpenStreetMap API to convert the geographical reference to @@ -314,21 +320,21 @@ Functions -- Function: olc-is-valid code &key compound Returns non-‘nil’ if CODE is a valid open location code. If - COMPOUND is non-nil, then check only up to the first space - character so non-nil is returned for strings that look like + COMPOUND is non-‘nil’, then check only up to the first space + character so non-‘nil’ is returned for strings that look like compound codes. -- Function: olc-is-short code &key compound Returns non-‘nil’ if CODE is a valid short location code. If - COMPOUND is non-nil, then check only up to the first space - character so non-nil is returned for strings that look like + COMPOUND is non-‘nil’, then check only up to the first space + character so non-‘nil’ is returned for strings that look like compound codes. Returns ‘nil’ for valid full and for invalid codes. -- Function: olc-is-full code &key compound Returns non-‘nil’ if CODE is a valid full open location code. If - COMPOUND is non-nil, then check only up to the first space - character so non-nil is returned for strings that look like + COMPOUND is non-‘nil’, then check only up to the first space + character so non-‘nil’ is returned for strings that look like compound codes. Returns ‘nil’ for valid short and for invalid codes. @@ -351,18 +357,18 @@ Index * olc-area-p: olc-area. (line 13) * olc-decode: Functions. (line 21) * olc-encode: Functions. (line 6) -* olc-is-full: Functions. (line 124) -* olc-is-short: Functions. (line 117) -* olc-is-valid: Functions. (line 111) +* olc-is-full: Functions. (line 130) +* olc-is-short: Functions. (line 123) +* olc-is-valid: Functions. (line 117) * olc-parse-create: olc-parse. (line 9) * olc-parse-grid: olc-parse. (line 18) * olc-parse-pairs: olc-parse. (line 13) * olc-parse-precision: olc-parse. (line 25) * olc-parse-short: olc-parse. (line 22) -* olc-recover: Functions. (line 72) -* olc-recover-compound: Functions. (line 84) -* olc-shorten: Functions. (line 35) -* olc-shorten-compound: Functions. (line 48) +* olc-recover: Functions. (line 78) +* olc-recover-compound: Functions. (line 92) +* olc-shorten: Functions. (line 41) +* olc-shorten-compound: Functions. (line 54) @@ -373,7 +379,7 @@ Node: olc-area1277 Node: olc-parse2205 Node: Errors3435 Node: Functions7375 -Node: Index13244 +Node: Index13700 End Tag Table diff --git a/olc.texi b/olc.texi index c4864079338126af1adbe7b27f729616d34bd1e4..48614e18b68d37e5d73aac4030e72f798f643da1 100644 --- a/olc.texi +++ b/olc.texi @@ -246,6 +246,11 @@ if the code can't be parsed, and @code{olc-decode-error} if it can't be decoded (e.g. a padded shortened code, a padded code with grid coordinates, an empty code, and so forth). +If @var{format} is @samp{area} (the default), the returned value is an +full open location code. If @var{format} is @samp{latlon} it is a list +(@var{latitude} @var{longitude}) representing the center of the +location. + @example @group (olc-decode "9FCQ9HXG+4CG") @@ -254,6 +259,8 @@ coordinates, an empty code, and so forth). @result{} 58.3978125 (olc-area-lon (olc-decode "9FCQ9HXG+4CG")) @result{} 15.576078125 +(olc-decode "9FCQ9HXG+4CG" :format 'latlon) +@result{} (58.3978125 15.576078125) @end group @end example @end defun @@ -278,15 +285,15 @@ or shortened code, of if @var{limit} is not even. @defun olc-shorten-compound code &key limit Shorten @var{code}, which must be a full open location code, finding a -reference near the encoded location. If @var{limit} is non-nil, then -the code will be shortened by at most that many digits. If the code -can't be shortened, the original code is returned. +reference near the encoded location. If @var{limit} is non-@code{nil}, +then the code will be shortened by at most that many digits. If the +code can't be shortened, the original code is returned. -If @var{zoom} is non-nil, then limit references to that zoom level. -The default is 8 and the maximum is 18. Higher zoom levels yield more -precise but longer references. Lower zoom levels yield simpler -references but longer codes. The default seems to usually produce -codes with four characters before the plus sign. +If @var{zoom} is non-@code{nil}, then limit references to that zoom +level. The default is 8 and the maximum is 18. Higher zoom levels +yield more precise but longer references. Lower zoom levels yield +simpler references but longer codes. The default seems to usually +produce codes with four characters before the plus sign. @code{olc-shorten-error} is raised if @var{code} is a padded or shortened code, of if @var{limit} is not even. @@ -309,33 +316,37 @@ shortened code, of if @var{limit} is not even. Recover the closest point to coordinates @var{lat} and @var{lon} with a code that can be shortened to @var{code}. If @var{format} is @code{latlon}, then the center of the recovered area (@var{latitude} . -@var{longitude}) is returned. If @var{format} is @code{area} (or any other -value), the returned value is an full open location code. +@var{longitude}) is returned. + +If @var{format} is @samp{area} (the default), the returned value is an +full open location code. If @var{format} is @samp{latlon} it is a list +(@var{latitude} @var{longitude}) representing the center of the +location. @example @group (olc-recover "+2VX" 51.3701125 -1.217765625) @result{} "9C3W9QCJ+2VX" (olc-recover "+2VX" 51.3701125 -1.217765625 :format 'latlon) -@result{} (51.370112500000005 . -1.2177656250000002) +@result{} (51.370112500000005 -1.2177656250000002) @end group @end example @end defun -@defun olc-recover-compound arg1 &optional arg2 &key format +@defun olc-recover-compound code &key ref format Recover a shortened code @i{without} the reference latitude and longitude. -When called with one argument, it must be a string consisting of a -shortened open location code followed by whitespace and a geographical -location. - -When called with two strings, the first must be a shortened open -location code and the second if the geographical location. +@var{code} is the (shortened) code to decode. @var{ref} is either +@code{nil} or the geographical reference to use instead of latitude +and longitude. If @var{ref} is @code{nil}, then @var{code} must end +with the geographical reference, separated from the code by +whitespace. -Optionally, the last argument in either case can be a symbol -indicating the format of the return value (see @code{olc-recover} for -details). +If @var{format} is @samp{area} (the default), the returned value is an +full open location code. If @var{format} is @samp{latlon} it is a list +(@var{latitude} @var{longitude}) representing the center of the +location. @example @group @@ -344,7 +355,7 @@ details). (olc-recover-compound "M24Q+89" "Mutitjulu") @result{} "5Q6HM24Q+89" (olc-recover-compound "M24Q+89" "Mutitjulu" :format 'latlon) -@result{} (-25.344187500000004 . 131.0384375) +@result{} (-25.344187500000004 131.0384375) @end group @end example @@ -356,24 +367,25 @@ the API (e.g., one request per second, tops, allowed). @defun olc-is-valid code &key compound Returns non-@code{nil} if @var{code} is a valid open location code. If -@var{compound} is non-nil, then check only up to the first space -character so non-nil is returned for strings that look like compound -codes. +@var{compound} is non-@code{nil}, then check only up to the first +space character so non-@code{nil} is returned for strings that look +like compound codes. @end defun @defun olc-is-short code &key compound Returns non-@code{nil} if @var{code} is a valid short location code. -If @var{compound} is non-nil, then check only up to the first space -character so non-nil is returned for strings that look like compound -codes. Returns @code{nil} for valid full and for invalid codes. +If @var{compound} is non-@code{nil}, then check only up to the first +space character so non-@code{nil} is returned for strings that look +like compound codes. Returns @code{nil} for valid full and for invalid +codes. @end defun @defun olc-is-full code &key compound Returns non-@code{nil} if @var{code} is a valid full open location -code. If @var{compound} is non-nil, then check only up to the first -space character so non-nil is returned for strings that look like -compound codes. Returns @code{nil} for valid short and for invalid -codes. +code. If @var{compound} is non-@code{nil}, then check only up to the +first space character so non-@code{nil} is returned for strings that +look like compound codes. Returns @code{nil} for valid short and for +invalid codes. @end defun diff --git a/test/olctest.el b/test/olctest.el index 6bcf479162b632f81283a197adefc9ab7524eafd..cc1ec394f02ddc62fa226842a739044176e80d3c 100644 --- a/test/olctest.el +++ b/test/olctest.el @@ -388,8 +388,6 @@ )) - - (defun olctest-issue-1 () (olctest-testcase "local:issue-1" (olctest-assert-error (:exp (wrong-type-argument) :msg "F1") @@ -412,11 +410,11 @@ :act (olc-recover-compound "9FFV9VH8+9C" :ref "Antarctica") :msg "O1") - (olctest-equal :exp '(-89.99875 . -179.99875) + (olctest-equal :exp '(-89.99875 -179.99875) :act (olc-recover "22222222+" 0 0 :format 'latlon) :msg "O4") - (olctest-equal :exp '(-89.99875 . -179.99875) + (olctest-equal :exp '(-89.99875 -179.99875) :act (olc-recover-compound "22222222+" :format 'latlon) :msg "O4") @@ -496,7 +494,7 @@ )) (defun olctest-issue-5 () - (olctest-testcase "issue-5" + (olctest-testcase "local:issue-5" (olctest-string= :exp "https://nominatim.openstreetmap.org/search" :act (olc-nominatim-endpoint "search") :msg "1") @@ -512,7 +510,7 @@ :msg "3")))) (defun olctest-issue-6 () - (olctest-testcase "issue-6" + (olctest-testcase "local:issue-6" (olctest-equal :exp t :act (olc-is-valid "2222+")) (olctest-equal :exp t :act (olc-is-valid "2222+" :compound t)) (olctest-equal :exp nil :act (olc-is-valid "2222+ Sweden")) @@ -538,6 +536,13 @@ )) +(defun olctest-issue-7 () + (olctest-testcase "local:issue-7" + (olctest-equal :exp '(58.3978125 15.576078125) + :act (olc-decode "9FCQ9HXG+4CG" :format 'latlon) + :msg "1"))) + + (defvar olctest-selected-tests) (defmacro run-test (arg) @@ -556,6 +561,7 @@ (run-test validity) (run-test localtests) (run-test errors) + (run-test issue-7) (run-test issue-6) (run-test issue-5) (run-test issue-3)