From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Jean Louis Newsgroups: gmane.emacs.help Subject: rcd-template-eval - was Re: How to tame compiler? Date: Fri, 30 Apr 2021 22:38:30 +0300 Message-ID: References: <874kfn292f.fsf@disroot.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="30849"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mutt/2.0.6 (2021-03-06) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Fri Apr 30 21:47:30 2021 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lcZ6m-0007tf-RE for geh-help-gnu-emacs@m.gmane-mx.org; Fri, 30 Apr 2021 21:47:28 +0200 Original-Received: from localhost ([::1]:52880 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lcZ6l-0002I6-TV for geh-help-gnu-emacs@m.gmane-mx.org; Fri, 30 Apr 2021 15:47:27 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:42822) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lcZ5k-0002HE-Ku for help-gnu-emacs@gnu.org; Fri, 30 Apr 2021 15:46:24 -0400 Original-Received: from stw1.rcdrun.com ([217.170.207.13]:51609) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lcZ5i-0007Po-4C for help-gnu-emacs@gnu.org; Fri, 30 Apr 2021 15:46:24 -0400 Original-Received: from localhost ([::ffff:154.231.162.22]) (AUTH: PLAIN securesender, TLS: TLS1.3,256bits,ECDHE_RSA_AES_256_GCM_SHA384) by stw1.rcdrun.com with ESMTPSA id 0000000000046239.00000000608C5E8B.00005504; Fri, 30 Apr 2021 12:46:18 -0700 Mail-Followup-To: help-gnu-emacs@gnu.org Content-Disposition: inline In-Reply-To: <874kfn292f.fsf@disroot.org> Received-SPF: pass client-ip=217.170.207.13; envelope-from=bugs@gnu.support; helo=stw1.rcdrun.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:129222 Archived-At: * Jorge P. de Morais Neto [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/