all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Jean Louis <bugs@gnu.support>
To: help-gnu-emacs@gnu.org
Subject: rcd-template-eval - was Re: How to tame compiler?
Date: Fri, 30 Apr 2021 22:38:30 +0300	[thread overview]
Message-ID: <YIxctvC+YIFgrN4K@protected.localdomain> (raw)
In-Reply-To: <874kfn292f.fsf@disroot.org>

* Jorge P. de Morais Neto <jorge+list@disroot.org> [2021-04-30 17:29]:
> Hi all!
> 
> Em [2021-04-22 qui 10:46:59-0400], Stefan Monnier escreveu:
> 
> >> Is there a way to avoid these warnings?
> >
> > Yes: don't abuse `eval` ;-)
> 
> Jean Louis, could you provide a little more detail on what are you using
> ~eval~ for?  Some tasks accomplished by eval can be done more safely by
> other means.  For example, if you just want symbol indirection, you can
> use ~symbol-value~ (there is also ~symbol-function~).  If you want to
> apply a function object to a sequence of arguments, you can use ~apply~
> or ~funcall~.
> 
> I know little about Elisp; more experienced hackers may know about other
> mechanisms that avoid the need for ~eval~.

Gladly. I use it to expand some values in templates. That is very
handy and I use it already for many years. Normally it is for HTML and
WWW publishing. But I may use it for local reports on the fly. It is
very common beyond Emacs. It is similar to the nature of M4
pre-processing, which I have used back in past to create bunch of WWW
pages. It is similar to various server side templates with embedded
Perl or other programming languages, where there is more text and less
programming code.

(defvar rcd-template-delimiter-open "⟦")
(defvar rcd-template-delimiter-close "⟧")

(defun insert-rcd-lisp-brackets ()
  (interactive)
  (let ((open "⟦")
	(close "⟧"))
    (insert (format "%s () %s" open close))
    (backward-char 3)))

;; I have it in my key settings, when I press `C-c r i` I get this:
⟦ () ⟧ and then I can immediately write some expression like:
⟦ (+ 2 2) ⟧

if you now run the below function rcd-template-buffer-eval it will
show you 4 on that place. 

;; (define-key rcd-map "i" #'insert-rcd-lisp-brackets)

(defun rcd-template-eval (string &optional delimiters)
  "Evaluates Emacs Lisp enclosed by `rcd-template-delimiter-open' and `rcd-template-delimiter-close'.

Optional DELIMITERS list may be provided to change default
delimiters, first list member has to be the opening delimiter and
second the closing delimiter.

Space or new line has to follow `rcd-template-delimiter-open' and
precede `rcd-template-delimiter-close' for evaluation to get
invoked."
  (let* ((delimiters (or delimiters (list rcd-template-delimiter-open rcd-template-delimiter-close)))
	 (open (car delimiters))
	 (close (cadr delimiters)))
    (with-temp-buffer
      (insert string)
      (goto-char 0)
      (while (re-search-forward (rx (literal open)
				    (one-or-more (or blank "\n"))
				    (group (minimal-match (one-or-more anything)))
				    (one-or-more (or blank "\n"))
				    (literal close))
				nil t)
	;;(message "Found match")
	(let* ((lisp (car (read-from-string
			   (buffer-substring-no-properties
			    (1+ (match-beginning 0)) (1- (match-end 0))))))
	       (value (condition-case nil
			  (eval lisp)
			(error "")))
	       (value (string-or-empty-string value)))
	  ;; (message "HELLO: %s" (eval (format "%s" hello-name)))
	  (delete-region (match-beginning 0) (match-end 0))
	  (insert (format "%s" value))))
      (buffer-string))))

(defun rcd-template-buffer-eval ()
  (interactive)
  (let* ((buffer (buffer-string))
	 (mode major-mode)
	 (point (point)))
    (pop-to-buffer-same-window "Preview")
    (insert (rcd-template-eval buffer))
    (goto-char point)
    (funcall mode)
    ;;(espeak "Preview")
    ))

I have been using various templating systems before, and Perl was very
fast, then I switched to Common Lisp and used CL-EMB, and tried to
emulate it in Emacs Lisp, but syntax was kind of dirty like:

<% (something here) %>

or

<% @var some-variable %>

which I find easier like this:

⟦ some-variable ⟧

One can use any delimiters, I have chosen those ⟦ () ⟧
to input: type "C-x 8 RET 27e7" or "C-x 8 RET MATHEMATICAL RIGHT WHITE SQUARE BRACKET"

In general, this function will be silent with error "" and thus in
case that variable `some-variable' does not exist it will be empty.

Practical use cases:

Mass mailing lists are sent, and I wish to include recipient's
names in the template: ⟦ to-name ⟧ would expand into their full
name.

⟦ (gold-price-kg 1) ⟧ would expand to current gold price, there is
no need for me to change the body text of the email. Prices are
updated automatically, same for EUR/USD/GBP and other currencies.

⟦ (usd (gold-price-kg)) ⟧ would expand into US $57191

⟦ to-email ⟧ would expand into their email address

⟦ unsubscribe-url ⟧ would expand into the per recipient customized
URL to unsubscribe

Time estimates can be caluclated and sent by email automatically
that use current dates expanded in a template, not static dates.

Similar for HTML and WWW publishing, static pages may be generated on
the fly, expanded into Lisp values and transferred to web servers.

Normally in Common Lisp, and CL-EMB templating package I would need to
submit something like variables or list of variables, list alists to
get variables expanded. But I prefer that it works with any variables.

Instead of:
(rcd-template-eval "Template ⟦ variable ⟧" '(variable "VALUE")) 

right now I prefer it this way:

(let* ((variable "VALUE")
       (template "Template ⟦ variable ⟧")
       (expanded (rcd-template-eval template)))
  expanded) ⇒ "Template VALUE"

However, there is problem as my programs are with lexical-binding
⇒ t, so then I have to watch to do following:

(let* ((variable "VALUE")
       (template "Template ⟦ variable ⟧")
       (lexical-binding nil)
       (expanded (rcd-template-eval template)))
  expanded) ⇒ "Template VALUE"

as otherwise it would not necessarily expand, depending where the
function is defined.

In the end this approach allows me to write plain text, Markdown,
Org mode, just anything, and get the Emacs Lisp programs expanded
before as pre-processing before the Markdown, Org mode or
Asciidoc, Restructured Text or other type of processing. It of
course works automatic.

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

Sign an open letter in support of Richard M. Stallman
https://stallmansupport.org/
https://rms-support-letter.github.io/




  reply	other threads:[~2021-04-30 19:38 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-22 14:43 How to tame compiler? Jean Louis
2021-04-22 14:46 ` Stefan Monnier
2021-04-22 15:47   ` Jean Louis
2021-04-22 16:06   ` Jean Louis
2021-04-30 13:31   ` Jorge P. de Morais Neto
2021-04-30 19:38     ` Jean Louis [this message]
2021-04-30 19:48     ` rcd-template-eval, much is in Org mode Jean Louis
2021-04-30 20:06       ` Tassilo Horn
2021-04-30 22:08       ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-04-30 23:04         ` Org mode rant Jean Louis
2021-05-01  0:46           ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  6:10             ` Jean Louis
2021-05-01  6:34               ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  9:41                 ` On markdown images Jean Louis
2021-05-01  9:59                   ` Yuri Khan
2021-05-01 10:18                     ` Jean Louis
2021-05-01 11:09                       ` Yuri Khan
2021-05-01 11:25                         ` Jean Louis
2021-05-02 19:30                         ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-03  5:43                           ` Yuri Khan
2021-05-03 17:08                             ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-03 23:22                               ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-04  2:39                   ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  5:00           ` Org mode rant Bastien
2021-05-01  5:10             ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  9:16             ` Jean Louis
2021-05-01 10:06               ` Bastien
2021-05-01 10:42                 ` Jean Louis
2021-05-01 10:10               ` Bastien
2021-05-01 11:19                 ` Jean Louis
2021-05-01 13:48                 ` [External] : " Drew Adams
2021-05-01 14:05                   ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01 10:10               ` Bastien
2021-04-30 20:23     ` eval myths - Re: How to tame compiler? Jean Louis
2021-04-30 22:11       ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-04-30 23:07         ` Jean Louis
2021-05-01  0:28           ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  8:13       ` tomas
2021-04-30 22:06     ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-04-30 22:20       ` Stefan Monnier
2021-04-30 22:31         ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-04-30 22:50           ` Stefan Monnier
2021-04-30 22:56             ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  0:44 ` Michael Heerdegen
2021-05-01  3:49   ` Stefan Monnier
2021-05-01  4:55     ` Michael Heerdegen
2021-05-01  6:34     ` Jean Louis
2021-05-01 13:38       ` Stefan Monnier
2021-05-01 16:19         ` Jean Louis
2021-05-02  5:41     ` Michael Heerdegen
2021-05-02  7:37       ` Jean Louis
2021-05-02  7:45       ` Jean Louis
2021-05-02  9:06         ` tomas
2021-05-02 11:18           ` Jean Louis
2021-05-02 12:24             ` tomas
2021-05-02 18:17               ` Jean Louis
2021-05-02 12:06           ` Stages of WWW development compared to Emacs Lisp development Jean Louis
2021-05-02 16:51             ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-02 18:37               ` Jean Louis
2021-05-02 16:45       ` How to tame compiler? Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-02 22:29       ` Stefan Monnier
2021-05-02 23:14         ` Jean Louis
2021-05-03  1:58           ` Eduardo Ochs
2021-05-03  6:51             ` Eval in templates - " Jean Louis
2021-05-01  4:53   ` Michael Heerdegen
2021-05-01  7:05     ` Jean Louis
2021-05-01  7:59       ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-01  6:03   ` Jean Louis
2021-05-01  6:17     ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-05-02  5:58     ` Michael Heerdegen
2021-05-02  6:54       ` Jean Louis
2021-05-03 21:39       ` Jean Louis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YIxctvC+YIFgrN4K@protected.localdomain \
    --to=bugs@gnu.support \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.