diff --git a/doc/org.texi b/doc/org.texi index 590ef9a2f..def5fa252 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -2269,12 +2269,14 @@ field, or press @kbd{C-c @}} to toggle the display of a grid. Formulas can reference the value of another field in two ways. Like in any other spreadsheet, you may reference fields with a letter/number combination like @code{B3}, meaning the 2nd field in the 3rd row. -@c Such references are always fixed to that field, they don't change -@c when you copy and paste a formula to a different field. So -@c Org's @code{B3} behaves like @code{$B$3} in other spreadsheets. @noindent -Org also uses another, more general operator that looks like this: +@vindex org-table-use-standard-references +Org prefers@footnote{Org will understand references typed by the user as +@samp{B4}, but it will not use this syntax when offering a formula for +editing. You can customize this behavior using the variable +@code{org-table-use-standard-references}.} to use another, more general +operator that looks like this: @example @@@var{row}$@var{column} @end example @@ -2286,23 +2288,25 @@ references make it possible to store a formula only once and use it in many fields without copying and modifying it. Column references can be absolute like @samp{1}, @samp{2},...@samp{@var{N}}, -or relative to the current column like @samp{+1} or @samp{-2}. +or relative to the current column like @samp{+1} or @samp{-2}. @code{$>} +references the last column in the table, and you can use offsets like +@code{$>-2}, meaning the third column from the right. The row specification only counts data lines and ignores horizontal separator -lines (hlines). You can use absolute row numbers @samp{1}...@samp{@var{N}}, -and row numbers relative to the current row like @samp{+3} or @samp{-1}. A -special case is @code{@@L} which stands for the last row in the +lines (hlines). Like with columns, you can use absolute row numbers +@samp{1}...@samp{@var{N}}, and row numbers relative to the current row like +@samp{+3} or @samp{-1}, and @code{@@>} references the last row in the table@footnote{For backward compatibility you can also use special names like @samp{$LR5} and @samp{$LR12} to refer in a stable way to the 5th and 12th field in the last row of the table. However, this syntax is deprecated, it -should not be used for new documents.}, and you can use offsets from it like -@code{@@L-2}. Or specify the row relative to one of the hlines: @samp{I} -refers to the first hline@footnote{Note that only hlines are counted that -@emph{separate} table lines. If the table starts with a hline above the -header, it does not count.}, @samp{II} to the second, etc@. @samp{-I} refers -to the first such line above the current line, @samp{+I} to the first such -line below the current line. You can also write @samp{III+2} which is the -second data line after the third hline in the table. +should not be used for new documents.}. You may also specify the row +relative to one of the hlines: @samp{I} refers to the first +hline@footnote{Note that only hlines are counted that @emph{separate} table +lines. If the table starts with a hline above the header, it does not +count.}, @samp{II} to the second, etc@. @samp{-I} refers to the first such +line above the current line, @samp{+I} to the first such line below the +current line. You can also write @samp{III+2} which is the second data line +after the third hline in the table. @samp{0} refers to the current row and column. Also, if you omit either the column or the row part of the reference, the current @@ -2603,7 +2607,7 @@ same formula will be used in all fields of that column, with the following very convenient exceptions: (i) If the table contains horizontal separator hlines, everything before the first such line is considered part of the table @emph{header} and will not be modified by column formulas. (ii) Fields that -already get a value from a fild/range formula will be left alone by column +already get a value from a field/range formula will be left alone by column formulas. These conditions make column formulas very easy to use. To assign a formula to a column, type it directly into any field in the @@ -2615,7 +2619,7 @@ and the current field replaced with the result. If the field contains only column, Org will only remember the most recently used formula. In the @samp{#+TBLFM:} line, column formulas will look like @samp{$4=$1+$2}. The left-hand side of a column formula can not be the name of column, it must be -the numeric column reference. +the numeric column reference or @code{$>}. Instead of typing an equation into the field, you may also use the following command: diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el index 06e310e38..7578b7654 100644 --- a/lisp/ob-exp.el +++ b/lisp/ob-exp.el @@ -248,8 +248,9 @@ This function is called by `org-babel-exp-do-export'. The code block will be evaluated. Optional argument SILENT can be used to inhibit insertion of results into the buffer." (when (and org-export-babel-evaluate - (not (equal hash (org-babel-exp-in-export-file (nth 0 info) - (org-babel-result-hash))))) + (not (and hash + (equal hash (org-babel-exp-in-export-file (nth 0 info) + (org-babel-result-hash)))))) (let ((lang (nth 0 info)) (body (nth 1 info))) ;; skip code blocks which we can't evaluate diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el index 4170381ec..8943dedee 100644 --- a/lisp/ob-latex.el +++ b/lisp/ob-latex.el @@ -72,10 +72,6 @@ This function is called by `org-babel-execute-src-block'." (let* ((out-file (cdr (assoc :file params))) (tex-file (org-babel-temp-file "latex-" ".tex")) (border (cdr (assoc :border params))) - (imagemagick (cdr (assoc :imagemagick params))) - (im-in-options (cdr (assoc :iminoptions params))) - (im-out-options (cdr (assoc :imoutoptions params))) - (pdfpng (cdr (assoc :pdfpng params))) (fit (or (cdr (assoc :fit params)) border)) (height (and fit (cdr (assoc :pdfheight params)))) (width (and fit (cdr (assoc :pdfwidth params)))) @@ -85,10 +81,10 @@ This function is called by `org-babel-execute-src-block'." (append (cdr (assoc :packages params)) org-export-latex-packages-alist))) (cond - ((and (string-match "\\.png$" out-file) (not imagemagick)) + ((string-match "\\.png$" out-file) (org-create-formula-image body out-file org-format-latex-options in-buffer)) - ((or (string-match "\\.pdf$" out-file) imagemagick) + ((string-match "\\.pdf$" out-file) (require 'org-latex) (with-temp-file tex-file (insert @@ -122,29 +118,13 @@ This function is called by `org-babel-execute-src-block'." (concat "\n\\begin{document}\n" body "\n\\end{document}\n"))) (org-export-latex-fix-inputenc)) (when (file-exists-p out-file) (delete-file out-file)) - (let ((transient-pdf-file (org-babel-latex-tex-to-pdf tex-file))) - (cond - ((string-match "\\.pdf$" out-file) - (rename-file transient-pdf-file out-file)) - (imagemagick - (convert-pdf - transient-pdf-file out-file im-in-options im-out-options) - (when (file-exists-p transient-pdf-file) - (delete-file transient-pdf-file)))))) + (rename-file (org-babel-latex-tex-to-pdf tex-file) out-file)) ((string-match "\\.\\([^\\.]+\\)$" out-file) - (error "can not create %s files, please specify a .png or .pdf file or try the :imagemagick header arguement" + (error "can not create %s files, please specify a .png or .pdf file" (match-string 1 out-file)))) nil) ;; signal that output has already been written to file body)) - -(defun convert-pdf (pdffile out-file im-in-options im-out-options) - "Generate a file from a pdf file using imagemagick." - (let ((cmd (concat "convert " im-in-options " " pdffile " " - im-out-options " " out-file))) - (message (concat "Converting pdffile file " cmd "...")) - (shell-command cmd))) - (defun org-babel-latex-tex-to-pdf (file) "Generate a pdf file according to the contents FILE. Extracted from `org-export-as-pdf' in org-latex.el." diff --git a/lisp/org-table.el b/lisp/org-table.el index d4d45a9ea..7f96cca5b 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -176,7 +176,7 @@ this line." :tag "Org Table Calculation" :group 'org-table) -(defcustom org-table-use-standard-references t +(defcustom org-table-use-standard-references 'from "Should org-mode work with table references like B3 instead of @3$2? Possible values are: nil never use them @@ -1133,7 +1133,7 @@ is always the old value." (eql (org-table-expand-lhs-ranges (mapcar (lambda (e) - (cons (org-table-formula-handle-@L (car e)) (cdr e))) + (cons (org-table-formula-handle-lastrc (car e)) (cdr e))) (org-table-get-stored-formulas)))) (dline (org-table-current-dline)) (ref (format "@%d$%d" dline col)) @@ -1975,6 +1975,10 @@ When NAMED is non-nil, look for a named equation." "\n"))) (defsubst org-table-formula-make-cmp-string (a) + (when (string-match "\\`$>" a) + ;; Fake a high number to make sure this is sorted at the end. + (setq a (org-table-formula-handle-lastrc a)) + (setq a (format "$%d" (+ 10000 (string-to-number (substring a 1)))))) (when (string-match "^\\(@\\([0-9]+\\)\\)?\\(\\$?\\([0-9]+\\)\\)?\\(\\$?[a-zA-Z0-9]+\\)?" a) (concat (if (match-end 2) (format "@%05d" (string-to-number (match-string 2 a))) "") @@ -1994,12 +1998,14 @@ When NAMED is non-nil, look for a named equation." (save-excursion (goto-char (org-table-end)) (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+TBLFM: *\\(.*\\)") - (setq strings (org-split-string (match-string 2) " *:: *")) + (setq strings (org-split-string (org-match-string-no-properties 2) + " *:: *")) (while (setq string (pop strings)) - (when (string-match "\\`\\(@[-+LI0-9.$@]+\\|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*[^ \t]\\)" string) + (when (string-match "\\`\\(@[-+I>0-9.$@]+\\|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\|>\\(?:[-+][0-9]+\\)?\\)\\) *= *\\(.*[^ \t]\\)" string) (setq scol (if (match-end 2) (match-string 2 string) (match-string 1 string)) + scol (if (= (string-to-char scol) ?>) (concat "$" scol) scol) eq (match-string 3 string) eq-alist (cons (cons scol eq) eq-alist)) (if (member scol seen) @@ -2388,9 +2394,10 @@ not overwrite the stored one." t t form))) (setq form0 form) ;; Insert the references to fields in same row - (while (string-match "\\$\\([0-9]+\\)" form) - (setq n (string-to-number (match-string 1 form)) - x (nth (1- (if (= n 0) n0 n)) fields)) + (while (string-match "\\$\\(\\([-+]\\)?[0-9]+\\)" form) + (setq n (+ (string-to-number (match-string 1 form)) + (if (match-end 2) n0 0)) + x (nth (1- (if (= n 0) n0 (max n 1))) fields)) (unless x (error "Invalid field specifier \"%s\"" (match-string 0 form))) (setq form (replace-match @@ -2632,19 +2639,29 @@ known that the table will be realigned a little later anyway." (org-table-get-specials) (let* ((eqlist (sort (org-table-get-stored-formulas) (lambda (a b) (string< (car a) (car b))))) + (eqlist1 (copy-sequence eqlist)) (inhibit-redisplay (not debug-on-error)) (line-re org-table-dataline-regexp) (thisline (org-current-line)) (thiscol (org-table-current-column)) - seen-fields + seen-fields lhs1 beg end entry eqlnum eqlname eqlname1 eql (cnt 0) eq a name name1) ;; Insert constants in all formulas (setq eqlist (mapcar (lambda (x) + (when (string-match "\\`$>" (car x)) + (setq lhs1 (car x)) + (setq x (cons (substring + (org-table-formula-handle-lastrc + (car x)) 1) + (cdr x))) + (if (assoc (car x) eqlist1) + (error "\"%s=\" formula tries to overwrite existing formula for column %s" + lhs1 (car x)))) (cons - (org-table-formula-handle-@L (car x)) + (org-table-formula-handle-lastrc (car x)) (org-table-formula-substitute-names - (org-table-formula-handle-@L (cdr x))))) + (org-table-formula-handle-lastrc (cdr x))))) eqlist)) ;; Split the equation list (while (setq eq (pop eqlist)) @@ -2702,6 +2719,7 @@ known that the table will be realigned a little later anyway." (org-table-goto-column (nth 2 a)) (push (append a (list (cdr eq))) eqlname1) (org-table-put-field-property :org-untouchable t))) + (setq eqlname1 (nreverse eqlname1)) ;; Now evaluate the column formulas, but skip fields covered by ;; field formulas @@ -2742,7 +2760,9 @@ known that the table will be realigned a little later anyway." (and all (message "Re-applying formulas...done")))))) (defun org-table-iterate (&optional arg) - "Recalculate the table until it does not change anymore." + "Recalculate the table until it does not change anymore. +The maximun number of iterations is 10, but you can chose a different value +with the prefix ARG." (interactive "P") (let ((imax (if arg (prefix-numeric-value arg) 10)) (i 0) @@ -2824,14 +2844,18 @@ them to individual field equations for each field." :orig-eqn e (caar res))))))) (nreverse res))) -(defun org-table-formula-handle-@L (s) - "Replace @L with the last row data row of the table." - (while (string-match "@L\\(-[0-9]+\\)?" s) +(defun org-table-formula-handle-lastrc (s) + "Replace @> / $> with the last row/column of the table." + (while (string-match "\\([@$]\\)>\\(-[0-9]+\\)?" s) (setq s (replace-match - (format "@%d" (+ (length org-table-dlines) -1 - (if (match-end 1) - (string-to-number (match-string 1 s)) - 0))) + (format "%s%d" + (match-string 1 s) + (+ (if (equal (match-string 1 s) "@") + (1- (length org-table-dlines)) + org-table-current-ncol) + (if (match-end 2) + (string-to-number (match-string 2 s)) + 0))) t t s))) s) @@ -2955,6 +2979,7 @@ Parameters get priority." (setq startline (org-current-line)) (while (setq entry (pop eql)) (setq type (cond + ((string-match "\\`$>" (car entry)) 'column) ((equal (string-to-char (car entry)) ?@) 'field) ((string-match "^[0-9]" (car entry)) 'column) (t 'named))) @@ -2963,7 +2988,7 @@ Parameters get priority." (insert (org-add-props (cdr title) nil 'face font-lock-comment-face)) (setq titles (remove title titles))) (if (equal key (car entry)) (setq startline (org-current-line))) - (setq s (concat (if (equal (string-to-char (car entry)) ?@) "" "$") + (setq s (concat (if (member (string-to-char (car entry)) '(?@ ?$)) "" "$") (car entry) " = " (cdr entry) "\n")) (remove-text-properties 0 (length s) '(face nil) s) (insert s)) @@ -3178,7 +3203,7 @@ With prefix ARG, apply the new formulas to the table." (let ((pos org-pos) (sel-win org-selected-window) eql var form) (goto-char (point-min)) (while (re-search-forward - "^\\(@[-+IL0-9.$@]+\\|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*\\(\n[ \t]+.*$\\)*\\)" + "^\\(@[-+I>0-9.$@]+\\|@?[0-9]+\\|\\$\\([a-zA-Z0-9]+\\|>[-+0-9]*\\)\\) *= *\\(.*\\(\n[ \t]+.*$\\)*\\)" nil t) (setq var (if (match-end 2) (match-string 2) (match-string 1)) form (match-string 3))