From 74f5eb2b7411806c5a787541c8380b5f548f2ccf Mon Sep 17 00:00:00 2001 From: Francois Fleuret Date: Sat, 15 Aug 2015 00:25:18 -0700 Subject: [PATCH] Initial commit. --- arithmlatex.el | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 arithmlatex.el diff --git a/arithmlatex.el b/arithmlatex.el new file mode 100644 index 0000000..7503e0e --- /dev/null +++ b/arithmlatex.el @@ -0,0 +1,93 @@ +;; -*- mode: emacs-lisp -*- + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This program is free software; you can redistribute it and/or ;; +;; modify it under the terms of the GNU General Public License as ;; +;; published by the Free Software Foundation; either version 3, or (at ;; +;; your option) any later version. ;; +;; ;; +;; This program is distributed in the hope that it will be useful, but ;; +;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; +;; General Public License for more details. ;; +;; ;; +;; You should have received a copy of the GNU General Public License ;; +;; along with this program. If not, see . ;; +;; ;; +;; Written by and Copyright (C) Francois Fleuret ;; +;; Contact for comments & bug reports ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; This short scripts performs arithmetic computations in a latex +;; file. It collects variables defined by \fflet{VARNAME}{VALUE} +;; expressions in the latex file, and updates the VALUE in the +;; expressions of the form \ffeval{EXPRESSION}{VALUE} + +;; Note that you have to add +;; +;; \newcommand{\fflet}[2]{} +;; \newcommand{\ffeval}[2]{#2} +;; +;; Somewhere in your latex file. +;; +;; EXAMPLE +;; \fflet{X}{12} \fflet{Y}{19 + X * (X + 3)} \ffeval{18 * Y}{} + + +(defun arithmlatex/eval (expression var-table) + (let ((nb-loops 0)) + (while (string-match "\\([A-Za-z][A-Za-z0-9_]*\\)" expression) + (setq nb-loops (1+ nb-loops) + expression + (replace-match + (concat "(" (gethash (sxhash (match-string 1 expression)) var-table) ")") + t t expression)) + (when (> nb-loops 100) (error "Too many evaluation levels")) + )) + (calc-eval expression)) + +(defun arithmlatex (&optional universal) (interactive "P") + (let ((var-table (make-hash-table)) + (nb-changes 0)) + + (save-excursion + + ;; First we collect the variable definitions + (goto-char (point-min)) + (while (re-search-forward + "\\fflet{\\([^}]*\\)}{\\([^}]*\\)}" + nil t) + (let ((a (match-string-no-properties 1)) + (b (match-string-no-properties 2))) + (if (gethash (sxhash a) var-table) + (error "%s is multiply defined" a)) + (puthash (sxhash a) b var-table) + )) + + ;; Then we evaluate the expressions + (goto-char (point-min)) + (while (re-search-forward + "\\ffeval{\\([^}]*\\)}{\\([^}]*\\)}" + nil t) + (let* ((a (match-string-no-properties 1)) + (b (match-string-no-properties 2)) + (start (match-beginning 2)) + (end (match-end 2)) + (v (condition-case nil (arithmlatex/eval a var-table) (error "???")))) + (if (not (stringp v)) (setq v "???")) + + ;; Do the change only if necessary + (unless (string= v b) + (setq nb-changes (1+ nb-changes)) + (unless universal + (kill-region start end) + (backward-char) + (insert v))) + )) + ) + + (if universal + (message "There would be %s substitutions" nb-changes) + (message "There have been %s substitutions" nb-changes)) + ) + ) -- 2.20.1