help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to run shell command with stream input, to get string output


From: Jean Louis
Subject: Re: How to run shell command with stream input, to get string output
Date: Thu, 4 Jul 2019 22:33:25 +0200
User-agent: Mutt/1.10.1 (2018-07-13)

* Marcin Borkowski <address@hidden> [2019-07-04 21:19]:
> > The data is not in files, it is in the database.
> 
> Ah, now that finally makes sense to me.
> 
> Unfortunately, I can't help with this - but thanks for your patience,
> I didn't get the problem earlier.

Majority of Website Revision Systems require
some templating mechanism, so I am just moving
from Common Lisp CL-EMB to doing the same in emacs.

Reference to Website Revision System:
https://www.gnu.org/philosophy/words-to-avoid.html#Content

I started with this one, it works reasonably well
for faxing from Emacs. Imagine multiple templates,
multiple faxes, variables like first name, last
name, fax numbers, need to be replaced in the
templates. 

(defun rcd/expand-@template@ (template plist)
  "Expands the template that contains @vars@ with plist member values from 
plist"
  (let ((rx (rx "@" (group (one-or-more (or (any alpha) "_"))) "@")))
    (with-temp-buffer
      (insert template)
      (goto-char 0)
      (while (re-search-forward rx nil t)
        (let* ((var-found (match-string 1))
               (var-plist (or (plist-get plist (intern var-found)) ""))
               (var-plist (if (numberp var-plist) (number-to-string var-plist) 
var-plist)))
          (replace-match var-plist nil nil)))
      (buffer-string))))

(defun rcd/xml-escape (any)
  (let ((type (type-of any)))
    (cond ((eq 'string type) (xml-escape-string any))
          ((eq 'integer type) (number-to-string any)))))

This one works better than xml-escape-string for
my purposes, maybe it is not efficient, but the
other one is not working in my templates.

(defun xml-escape (string)
  "Escape XML without matching problems"
  (let ((chars (string-to-list string))
        (nlist '()))
    (dolist (c chars (list-of-strings-to-string (reverse nlist)))
      (let ((char (char-to-string c)))
        (push 
         (cond ((string= ">" char) "&gt;")
               ((string= "<" char) "&lt;")
               ((string= "\"" char) "&quot;")
               ((string= "'" char) "&#39;")
               ((string= "&" char) "&amp;")
               (t char))
         nlist)))))

(defun rcd/expand-<%template%>-plist (template plist)
  "Expands the template that contains <% var %> with plist member values from 
plist"
    (let ((rx (rx "<%" (one-or-more (or blank "\n")) (group (minimal-match 
(one-or-more (or (any alpha) "-" "_")))) (one-or-more (or blank "\n")) 
"-escape" (one-or-more (or blank "\n")) "%>")))
    (with-temp-buffer
      (insert template)
      (goto-char (point-min))
      (while (re-search-forward rx nil t)
        (let* ((var-found (match-string 1))
               (value-found (or (plist-get plist (intern var-found)) nil))
               (var-plist (if value-found (plist-get plist (intern var-found)) 
nil)))
          (if (and var-found value-found var-plist)
              (replace-match (xml-escape var-plist) nil nil)
            (replace-match (concat "<% " var-found " %>") nil nil))))
      (let ((rx2 (rx "<%" (one-or-more (or blank "\n")) (group (minimal-match 
(one-or-more (or (any alpha) "-" "_")))) (one-or-more (or blank "\n")) "%>")))
        (goto-char (point-min))
        (while (re-search-forward rx2 nil t)
          (let* ((var-found (match-string 1))
                 (value-found (or (plist-get plist (intern var-found)) nil))
                 (var-plist (if value-found (or (plist-get plist (intern 
var-found)) (concat "<% " var-found " %>")))))
            (if (and var-found value-found)
                (replace-match var-plist nil nil)
              (replace-match (concat "<% " var-found " %>" nil nil)))))
      (buffer-string)))))
          
(defun rcd/expand-<%template%>-eval (template)
    (let ((rx (rx "<%" (one-or-more (or blank "\n")) (group (minimal-match 
(one-or-more anything))) (one-or-more (or blank "\n")) "%>")))
      (with-temp-buffer
        (insert template)
        (goto-char (point-min))
        (while (re-search-forward rx nil t)
          (let* ((eval-found (match-string 1))
                 (eval-value (condition-case nil (eval (car (read-from-string 
eval-found))) (error "")))
                 (eval-value (if eval-value (format "%s" eval-value) "")))
            (if eval-found
                (replace-match eval-value nil nil)
              (replace-match "" nil nil))))
                (buffer-string))))

(defun rcd/expand-<%template%> (template plist)
  "Expands <% templates %> with plist, global variables and any functions"
  (let* ((plist (rcd/expand-<%template%>-plist template plist))
         (eval (rcd/expand-<%template%>-eval plist)))
    eval))

(defun gold-price-kg ()
      45553.12)
      
And here is working example.

;; (rcd/expand-<%template%> "<title><% (gold-price-kg) %></title> {<% 
title-some -escape %>} {<% title-some %>}" '(title-some "<<SOMETHING>>"))

If somebody wish to propose better regex let me
know.

Jean



reply via email to

[Prev in Thread] Current Thread [Next in Thread]