unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Expanding list into string within a command
@ 2020-12-06 19:46 Jean Louis
  2020-12-06 19:57 ` arthur miller
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Jean Louis @ 2020-12-06 19:46 UTC (permalink / raw)
  To: Help GNU Emacs


I would like to get this function to work, to convert geographical
coordinates notation from 5d15'57.76"S 35d8'22.65"E to decimal system
by using `proj' software and I wish to make generic function that will
accept any kind of format input to avoid hard coding.

This works well on command line:

$ cs2cs -f "%.6f" +proj=latlong +datum=WGS84 +to +proj=latlong +datum=WGS84
5d15'57.76"S 35d8'22.65"E
-5.266044	35.139625 0.000000

And I know how to make it when hard coded. Here I wish to expand it
maybe with macro.

This is the invocation of the function that I would like to get
working by feeding 2 strings, first being coordinates and second the
`cs2cs' format for conversions of coordinates.

(syogm-cs2cs "5d15'57.76\"S 35d8'22.65\"E" "-f \"%.6f\" +proj=latlong +datum=WGS84 +to +proj=latlong +datum=WGS84")

Error is:

"Rel. 6.1.0, May 15th, 2019
<cs2cs>: 
missing argument for -f
program abnormally terminated
"
Error probably comes from lack of my knowledge how to use macro
expansion as here one could see how I have imagined that it could
expand:

(defun syogm-cs2cs (coord-string cs2cs-format)
  (let* ((command "cs2cs")
	 (output (command-stream-in-out command coord-string `,(string-join (split-string cs2cs-format) " "))))
    output))

So I was thinking to use macro that will expand the list within a
command. Is there different better way to do this?

The below functions are related only in so far to maybe make these
above working.

This function here I could improve. This one is invoked many times by
many programs and I would not like changing it. One way to solve the
issue could be that I test for ARGS if it is list or not and convert
there. 
	 
(defun command-stream-in-out (command string &rest args)
  (let* ((uid (number-to-string (user-uid)))
	 (memory-dir (rcd-memory-dir))
	 (infile (concat memory-dir "command-input")))
    (string-to-file-force string infile)
    (with-temp-buffer
      (apply 'call-process command infile (current-buffer) nil args)
      (buffer-string))))

All below functions are only relevant for execution of above
functions.

(defun rcd-memory-dir ()
  (let ((xdg-runtime-dir (getenv "XDG_RUNTIME_DIR")))
    (if xdg-runtime-dir (slash-add xdg-runtime-dir)
      (if (and (file-directory-p "/dev/shm")
	       (file-writable-p "/dev/shm"))
	  (slash-add "/dev/shm")))))

(defun string-to-file-force (string file)
  "Prints string into file, matters not if file exists. Returns FILE as file name."
    (with-temp-file file
      (insert string))
    file)

(defun slash-add (path)
  "Adds slash `/` quickly on the end of string"
  (let ((last (substring (reverse path) 0 1)))
    (if (string= last "/") path
      (concat path "/"))))



^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: Expanding list into string within a command
  2020-12-06 19:46 Expanding list into string within a command Jean Louis
@ 2020-12-06 19:57 ` arthur miller
  2020-12-06 20:30   ` Jean Louis
  2020-12-06 19:57 ` [solved] " Jean Louis
  2020-12-06 20:07 ` arthur miller
  2 siblings, 1 reply; 6+ messages in thread
From: arthur miller @ 2020-12-06 19:57 UTC (permalink / raw)
  To: Jean Louis, Help GNU Emacs

"So I was thinking to use macro that will expand the list within a command."

Try smth like this:
(my-macro (command &rest list)
  (dolist (item `,@list)
    (dosnth with your list item here)))

Kind of, if that is what yiu want, I am not sure really what you are after here, but I use that as an idiom quite a lot.

I am not at home, just fast from my phone .....


-------- Originalmeddelande --------
Från: Jean Louis <bugs@gnu.support>
Datum: 2020-12-06 20:47 (GMT+01:00)
Till: Help GNU Emacs <help-gnu-emacs@gnu.org>
Ämne: Expanding list into string within a command


I would like to get this function to work, to convert geographical
coordinates notation from 5d15'57.76"S 35d8'22.65"E to decimal system
by using `proj' software and I wish to make generic function that will
accept any kind of format input to avoid hard coding.

This works well on command line:

$ cs2cs -f "%.6f" +proj=latlong +datum=WGS84 +to +proj=latlong +datum=WGS84
5d15'57.76"S 35d8'22.65"E
-5.266044       35.139625 0.000000

And I know how to make it when hard coded. Here I wish to expand it
maybe with macro.

This is the invocation of the function that I would like to get
working by feeding 2 strings, first being coordinates and second the
`cs2cs' format for conversions of coordinates.

(syogm-cs2cs "5d15'57.76\"S 35d8'22.65\"E" "-f \"%.6f\" +proj=latlong +datum=WGS84 +to +proj=latlong +datum=WGS84")

Error is:

"Rel. 6.1.0, May 15th, 2019
<cs2cs>:
missing argument for -f
program abnormally terminated
"
Error probably comes from lack of my knowledge how to use macro
expansion as here one could see how I have imagined that it could
expand:

(defun syogm-cs2cs (coord-string cs2cs-format)
  (let* ((command "cs2cs")
         (output (command-stream-in-out command coord-string `,(string-join (split-string cs2cs-format) " "))))
    output))

So I was thinking to use macro that will expand the list within a
command. Is there different better way to do this?

The below functions are related only in so far to maybe make these
above working.

This function here I could improve. This one is invoked many times by
many programs and I would not like changing it. One way to solve the
issue could be that I test for ARGS if it is list or not and convert
there.

(defun command-stream-in-out (command string &rest args)
  (let* ((uid (number-to-string (user-uid)))
         (memory-dir (rcd-memory-dir))
         (infile (concat memory-dir "command-input")))
    (string-to-file-force string infile)
    (with-temp-buffer
      (apply 'call-process command infile (current-buffer) nil args)
      (buffer-string))))

All below functions are only relevant for execution of above
functions.

(defun rcd-memory-dir ()
  (let ((xdg-runtime-dir (getenv "XDG_RUNTIME_DIR")))
    (if xdg-runtime-dir (slash-add xdg-runtime-dir)
      (if (and (file-directory-p "/dev/shm")
               (file-writable-p "/dev/shm"))
          (slash-add "/dev/shm")))))

(defun string-to-file-force (string file)
  "Prints string into file, matters not if file exists. Returns FILE as file name."
    (with-temp-file file
      (insert string))
    file)

(defun slash-add (path)
  "Adds slash `/` quickly on the end of string"
  (let ((last (substring (reverse path) 0 1)))
    (if (string= last "/") path
      (concat path "/"))))



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [solved] Re: Expanding list into string within a command
  2020-12-06 19:46 Expanding list into string within a command Jean Louis
  2020-12-06 19:57 ` arthur miller
@ 2020-12-06 19:57 ` Jean Louis
  2020-12-06 20:07 ` arthur miller
  2 siblings, 0 replies; 6+ messages in thread
From: Jean Louis @ 2020-12-06 19:57 UTC (permalink / raw)
  To: Jean Louis; +Cc: Help GNU Emacs

* Jean Louis <bugs@gnu.support> [2020-12-06 22:47]:
> (defun syogm-cs2cs (coord-string cs2cs-format)
>   (let* ((command "cs2cs")
> 	 (output (command-stream-in-out command coord-string `,(string-join (split-string cs2cs-format) " "))))
>     output))

I have made new function to replace `command-stream-in-out' with:

(defun rcd-command-output-from-input (program input &rest args)
  "Returns output from PROGRAM INPUT with optional ARGS"
  (let* ((output (with-temp-buffer
		  (insert input)
		  (apply #'call-process-region nil nil program nil t nil args)
		  (buffer-string))))
    output))

and I have to use `apply' to get it working. I think this is solved.

I found a tip here:
https://stackoverflow.com/questions/629699/common-lisp-working-with-rest-parameters

As now I got it that `args' is a list.





^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: Expanding list into string within a command
  2020-12-06 19:46 Expanding list into string within a command Jean Louis
  2020-12-06 19:57 ` arthur miller
  2020-12-06 19:57 ` [solved] " Jean Louis
@ 2020-12-06 20:07 ` arthur miller
  2020-12-06 20:34   ` dms2dd " Jean Louis
  2 siblings, 1 reply; 6+ messages in thread
From: arthur miller @ 2020-12-06 20:07 UTC (permalink / raw)
  To: Jean Louis, Help GNU Emacs

Maybe I was too fast, didn't show how to use macroexample:

(defmacro with-command (cmdname &rest args)

(dolist (arg args)

 .... do your thing here .... ))

Now when you use it :

(with-command ls -l -h -s)

If you really want to parse those args or do something with them. But I think it is better to build a string and pass them that way to a command.


-------- Originalmeddelande --------
Från: Jean Louis <bugs@gnu.support>
Datum: 2020-12-06 20:47 (GMT+01:00)
Till: Help GNU Emacs <help-gnu-emacs@gnu.org>
Ämne: Expanding list into string within a command


I would like to get this function to work, to convert geographical
coordinates notation from 5d15'57.76"S 35d8'22.65"E to decimal system
by using `proj' software and I wish to make generic function that will
accept any kind of format input to avoid hard coding.

This works well on command line:

$ cs2cs -f "%.6f" +proj=latlong +datum=WGS84 +to +proj=latlong +datum=WGS84
5d15'57.76"S 35d8'22.65"E
-5.266044       35.139625 0.000000

And I know how to make it when hard coded. Here I wish to expand it
maybe with macro.

This is the invocation of the function that I would like to get
working by feeding 2 strings, first being coordinates and second the
`cs2cs' format for conversions of coordinates.

(syogm-cs2cs "5d15'57.76\"S 35d8'22.65\"E" "-f \"%.6f\" +proj=latlong +datum=WGS84 +to +proj=latlong +datum=WGS84")

Error is:

"Rel. 6.1.0, May 15th, 2019
<cs2cs>:
missing argument for -f
program abnormally terminated
"
Error probably comes from lack of my knowledge how to use macro
expansion as here one could see how I have imagined that it could
expand:

(defun syogm-cs2cs (coord-string cs2cs-format)
  (let* ((command "cs2cs")
         (output (command-stream-in-out command coord-string `,(string-join (split-string cs2cs-format) " "))))
    output))

So I was thinking to use macro that will expand the list within a
command. Is there different better way to do this?

The below functions are related only in so far to maybe make these
above working.

This function here I could improve. This one is invoked many times by
many programs and I would not like changing it. One way to solve the
issue could be that I test for ARGS if it is list or not and convert
there.

(defun command-stream-in-out (command string &rest args)
  (let* ((uid (number-to-string (user-uid)))
         (memory-dir (rcd-memory-dir))
         (infile (concat memory-dir "command-input")))
    (string-to-file-force string infile)
    (with-temp-buffer
      (apply 'call-process command infile (current-buffer) nil args)
      (buffer-string))))

All below functions are only relevant for execution of above
functions.

(defun rcd-memory-dir ()
  (let ((xdg-runtime-dir (getenv "XDG_RUNTIME_DIR")))
    (if xdg-runtime-dir (slash-add xdg-runtime-dir)
      (if (and (file-directory-p "/dev/shm")
               (file-writable-p "/dev/shm"))
          (slash-add "/dev/shm")))))

(defun string-to-file-force (string file)
  "Prints string into file, matters not if file exists. Returns FILE as file name."
    (with-temp-file file
      (insert string))
    file)

(defun slash-add (path)
  "Adds slash `/` quickly on the end of string"
  (let ((last (substring (reverse path) 0 1)))
    (if (string= last "/") path
      (concat path "/"))))



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Expanding list into string within a command
  2020-12-06 19:57 ` arthur miller
@ 2020-12-06 20:30   ` Jean Louis
  0 siblings, 0 replies; 6+ messages in thread
From: Jean Louis @ 2020-12-06 20:30 UTC (permalink / raw)
  To: arthur miller; +Cc: Help GNU Emacs

* arthur miller <arthur.miller@live.com> [2020-12-06 22:57]:
> "So I was thinking to use macro that will expand the list within a command."
> 
> Try smth like this:
> (my-macro (command &rest list)
>   (dolist (item `,@list)
>     (dosnth with your list item here)))
> 
> Kind of, if that is what yiu want, I am not sure really what you are after here, but I use that as an idiom quite a lot.

Thank you.

I had to use `apply' when passing `args' that I get from &rest

Now I have made the function better that takes input as string,
processes outside command and returns output as string:

(defun rcd-command-output-from-input (program input &rest args)
  "Returns output from PROGRAM INPUT with optional ARGS"
  (let* ((output (with-temp-buffer
		  (insert input)
		  (apply #'call-process-region nil nil program t t nil args)
		  (buffer-string))))
    output))

Which is also handy for some text processing like:

(defun markdown (text)
  (rcd-command-output-from-input "markdown" text))

(markdown "## Hello")
"<h2>Hello</h2>
"

Then I have improved the generic function to accept any `cs2cs'
format which is tool for conversion of geographic coordinates:

(defun syogm-cs2cs (coord-string &rest cs2cs-format)
  (let* ((command "cs2cs")
	 (cs2cs (apply #'rcd-command-output-from-input command coord-string cs2cs-format))
	 (output (string-trim cs2cs))
	 (output (split-string output "\t"))
	 (lat (pop output))
	 (output (split-string (car output) " "))
	 (lon (pop output)))
    (format "%s %s" lat lon)))

And now this works:

(syogm-cs2cs "5d15'57.76\"S 35d8'22.65\"E" "-f" "%.6f" "+proj=latlong" "+datum=WGS84" "+to" "+proj=latlong" "+datum=WGS84")

Then I can make new functions like:

(defun syogm-dms2dd (coord-string)
  "Convert DMS degree, minutes and seconds notation to DD decimal notation"
  (syogm-cs2cs coord-string "-f" "%.6f" "+proj=latlong" "+datum=WGS84" "+to" "+proj=latlong" "+datum=WGS84"))

Then it converts to acceptable result from degree, minutes,
seconds to decimal notation:

(syogm-dms2dd "5d15'57.76\"S 35d8'22.65\"E")
"-5.266044 35.139625"

as then I can convert Ugandan UTM zone 36N with geodetic datum
ARC1960 easier to WGS84 system used on mobile devices and maps of
today:

(defun syogm-convert-arc-1964-utm-36N-to-wgs-84 (earthing-northing)
  "Converts UTM Zone 36N Arc 1960 geodetic datum to WGS84"
  (syogm-cs2cs earthing-northing "-f" "%.5f" "EPSG:21096" "EPSG:4326"))

(syogm-convert-arc-1964-utm-36N-to-wgs-84 "137878 -125964")
"-1.14052 29.74755"

Which is final result I wanted to get, as only so I can request
download of maps from online providers.

Although I have been doing that conversion myself with Common Lisp already, but now I just wish to use external tool.

(defun ll-number (d)
  (let ((l (- (length d) 1)))
    (if (integerp (read-from-string (first-char d)))
	(substring d 0 l)
	d)))

(defun ll-parts (coord)
  (let ((ll-list (split-by-one-space coord)))
    (delete-if #'string-emptyp ll-list)
    (setf ll-list (map 'list #'(lambda (s) (string-trim '(#\Space) s)) ll-list))
    (setf ll-list (map 'list #'(lambda (s) (ll-number s)) ll-list))
    ll-list))

(defun dms2dd-degrees (d)
  (truncate d))

(defun dms2dd-minutes (m)
  (float (/ m 60)))

(defun dms2dd-seconds (s)
  (float (/ s 3600)))

(defun dms2dd (coord)
  (let* ((ll-list (ll-parts coord))
	 (degrees (car ll-list))
	 (minutes (cadr ll-list))
	 (seconds (caddr ll-list))
	 (cardinal (cadddr ll-list))
	 (dd (+ (dms2dd-degrees (read-from-string degrees))
		(dms2dd-minutes (read-from-string minutes))
		(dms2dd-seconds (read-from-string seconds)))))
	 (if (or (string= "S" cardinal) (string= "W" cardinal))
	     (- dd)
	     dd)))



^ permalink raw reply	[flat|nested] 6+ messages in thread

* dms2dd Re: Expanding list into string within a command
  2020-12-06 20:07 ` arthur miller
@ 2020-12-06 20:34   ` Jean Louis
  0 siblings, 0 replies; 6+ messages in thread
From: Jean Louis @ 2020-12-06 20:34 UTC (permalink / raw)
  To: arthur miller; +Cc: Help GNU Emacs

I have actually forgot that I have already transitioned Common Lisp to
Emacs Lisp to convert DMS to DD coordinates.

(defun geo/dms-parse (dms)
  (let* ((cardinal (cond ((string-match "N" dms) "N")
			 ((string-match "S" dms) "S")
			 ((string-match "E" dms) "E")
			 ((string-match "W" dms) "W")
			 (t (error "No cardinal direction found"))))
	 (parts (string-replace-non-digits-for-spaces dms))
	 (parts (string-trim parts))
	 (parts (string-replace-shorten-spaces parts))
	 (parts (split-string parts))
	 (degrees (string-to-number (car parts)))
	 (minutes (string-to-number (cadr parts)))
	 (seconds (string-to-number (caddr parts))))
    (list degrees minutes seconds cardinal)))

(defun geo/dms2dd-degrees (d)
  (truncate d))

(defun geo/dms2dd-minutes (m)
  (float (/ m 60.0)))

(defun geo/dms2dd-seconds (s)
  (float (/ s 3600.0)))

(defun geo/dms2dd (dms)
  "Converts DMS value to DD geo value"
  (let* ((dms (geo/dms-parse dms))
	 (degrees (car dms))
	 (minutes (cadr dms))
	 (seconds (caddr dms))
	 (cardinal (cadddr dms))
	 (dd (+ (geo/dms2dd-degrees degrees)
		(geo/dms2dd-minutes minutes)
		(geo/dms2dd-seconds seconds))))
    (cond ((string= "S" cardinal) (- dd))
	  ((string= "W" cardinal) (- dd))
	  (t dd))))



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-12-06 20:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-12-06 19:46 Expanding list into string within a command Jean Louis
2020-12-06 19:57 ` arthur miller
2020-12-06 20:30   ` Jean Louis
2020-12-06 19:57 ` [solved] " Jean Louis
2020-12-06 20:07 ` arthur miller
2020-12-06 20:34   ` dms2dd " Jean Louis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).