diff options
| author | Vincent Belaïche | 2011-06-27 08:18:45 +0200 |
|---|---|---|
| committer | Vincent Belaïche | 2011-06-27 08:18:45 +0200 |
| commit | cedc73f2fd66ec5f7a796592305fad41cb2089f3 (patch) | |
| tree | f7791e52439467d50ee189b5905e7de8e44fafa7 | |
| parent | 5e5d49b6d4b736e96be98d8e392c846bbc803142 (diff) | |
| download | emacs-cedc73f2fd66ec5f7a796592305fad41cb2089f3.tar.gz emacs-cedc73f2fd66ec5f7a796592305fad41cb2089f3.zip | |
(ses-relocate-range): Keep rest of arguments for ses-range.
(ses--clean-!, ses--clean-_): New functions.
(ses-range): Add configurability of readout order, and conversion to Calc vector.
| -rw-r--r-- | lisp/ChangeLog | 8 | ||||
| -rw-r--r-- | lisp/ses.el | 131 |
2 files changed, 130 insertions, 9 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index f7b1a336c88..f32ea602729 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | 2011-06-27 Vincent Belaïche <vincentb1@users.sourceforge.net> | 1 | 2011-06-27 Vincent Belaïche <vincentb1@users.sourceforge.net> |
| 2 | 2 | ||
| 3 | * ses.el (ses-relocate-range): Keep rest of arguments for | ||
| 4 | ses-range. | ||
| 5 | (ses--clean-!, ses--clean-_): New functions. | ||
| 6 | (ses-range): Add configurability of readout order, and conversion | ||
| 7 | to Calc vector. | ||
| 8 | |||
| 9 | 2011-06-27 Vincent Belaïche <vincentb1@users.sourceforge.net> | ||
| 10 | |||
| 3 | * ses.el (ses-repair-cell-reference-all): New function. | 11 | * ses.el (ses-repair-cell-reference-all): New function. |
| 4 | (ses-cell-symbol): Set macro as safe, so that it can be used in | 12 | (ses-cell-symbol): Set macro as safe, so that it can be used in |
| 5 | formulas. | 13 | formulas. |
diff --git a/lisp/ses.el b/lisp/ses.el index 2e6c24ab5e8..2e23e49810a 100644 --- a/lisp/ses.el +++ b/lisp/ses.el | |||
| @@ -1495,7 +1495,7 @@ if the range was altered." | |||
| 1495 | (funcall field (ses-sym-rowcol min)))) | 1495 | (funcall field (ses-sym-rowcol min)))) |
| 1496 | ;; This range has changed size. | 1496 | ;; This range has changed size. |
| 1497 | (setq ses-relocate-return 'range)) | 1497 | (setq ses-relocate-return 'range)) |
| 1498 | (list 'ses-range min max)))) | 1498 | `(ses-range ,min ,max ,@(cdddr range))))) |
| 1499 | 1499 | ||
| 1500 | (defun ses-relocate-all (minrow mincol rowincr colincr) | 1500 | (defun ses-relocate-all (minrow mincol rowincr colincr) |
| 1501 | "Alter all cell values, symbols, formulas, and reference-lists to relocate | 1501 | "Alter all cell values, symbols, formulas, and reference-lists to relocate |
| @@ -3171,15 +3171,128 @@ is safe or user allows execution anyway. Always returns t if | |||
| 3171 | ;; Standard formulas | 3171 | ;; Standard formulas |
| 3172 | ;;---------------------------------------------------------------------------- | 3172 | ;;---------------------------------------------------------------------------- |
| 3173 | 3173 | ||
| 3174 | (defmacro ses-range (from to) | 3174 | (defun ses--clean-! (&rest x) |
| 3175 | "Expands to a list of cell-symbols for the range. The range automatically | 3175 | "Clean by delq list X from any occurrence of `nil' or `*skip*'." |
| 3176 | expands to include any new row or column inserted into its middle. The SES | 3176 | (delq nil (delq '*skip* x))) |
| 3177 | library code specifically looks for the symbol `ses-range', so don't create an | 3177 | |
| 3178 | alias for this macro!" | 3178 | (defun ses--clean-_ (x y) |
| 3179 | (let (result) | 3179 | "Clean list X by replacing by Y any occurrence of `nil' or `*skip*'. |
| 3180 | |||
| 3181 | This will change X by making setcar on its cons cells." | ||
| 3182 | (let ((ret x) ret-elt) | ||
| 3183 | (while ret | ||
| 3184 | (setq ret-elt (car ret)) | ||
| 3185 | (when (memq ret-elt '(nil *skip*)) | ||
| 3186 | (setcar ret y)) | ||
| 3187 | (setq ret (cdr ret)))) | ||
| 3188 | x) | ||
| 3189 | |||
| 3190 | (defmacro ses-range (from to &rest rest) | ||
| 3191 | "Expands to a list of cell-symbols for the range going from | ||
| 3192 | FROM up to TO. The range automatically expands to include any | ||
| 3193 | new row or column inserted into its middle. The SES library code | ||
| 3194 | specifically looks for the symbol `ses-range', so don't create an | ||
| 3195 | alias for this macro! | ||
| 3196 | |||
| 3197 | By passing in REST some flags one can configure the way the range | ||
| 3198 | is read and how it is formatted. | ||
| 3199 | |||
| 3200 | In the sequel we assume that cells A1, B1, A2 B2 have respective values | ||
| 3201 | 1 2 3 and 4 for examplication. | ||
| 3202 | |||
| 3203 | Readout direction is specified by a `>v', '`>^', `<v', `<^', | ||
| 3204 | `v>', `v<', `^>', `^<' flag. For historical reasons, in absence | ||
| 3205 | of such a flag, a default direction of `^<' is assumed. This | ||
| 3206 | way `(ses-range A1 B2 ^>)' will evaluate to `(1 3 2 4)', | ||
| 3207 | while `(ses-range A1 B2 >^)' will evaluate to (3 4 1 2). | ||
| 3208 | |||
| 3209 | If the range is one row, then `>' can be used as a shorthand to | ||
| 3210 | `>v' or `>^', and `<' to `<v' or `<^'. | ||
| 3211 | |||
| 3212 | If the range is one column, then `v' can be used as a shorthand to | ||
| 3213 | `v>' or `v<', and `^' to `^>' or `v<'. | ||
| 3214 | |||
| 3215 | A `!' flag will remove all cells whose value is nil or `*skip*'. | ||
| 3216 | |||
| 3217 | A `_' flag will replace nil or `*skip*' by the value following | ||
| 3218 | the `_' flag. If the `_' flag is the last argument, then they are | ||
| 3219 | replaced by integer 0. | ||
| 3220 | |||
| 3221 | A `*', `*1' or `*2' flag will vectorize the range in the sense of | ||
| 3222 | Calc. See info node `(Calc) Top'. Flag `*' will output either a | ||
| 3223 | vector or a matrix depending on the number of rows, `*1' will | ||
| 3224 | flatten the result to a one row vector, and `*2' will make a | ||
| 3225 | matrix whatever the number of rows. | ||
| 3226 | |||
| 3227 | Warning: interaction with Calc is expermimental and may produce | ||
| 3228 | confusing results if you are not aware of Calc data format. Use | ||
| 3229 | `math-format-value' as a printer for Calc objects." | ||
| 3230 | (let (result-row | ||
| 3231 | result | ||
| 3232 | (prev-row -1) | ||
| 3233 | (reorient-x nil) | ||
| 3234 | (reorient-y nil) | ||
| 3235 | transpose vectorize | ||
| 3236 | (clean 'list)) | ||
| 3180 | (ses-dorange (cons from to) | 3237 | (ses-dorange (cons from to) |
| 3181 | (push (ses-cell-symbol row col) result)) | 3238 | (when (/= prev-row row) |
| 3182 | (cons 'list result))) | 3239 | (push result-row result) |
| 3240 | (setq result-row nil)) | ||
| 3241 | (push (ses-cell-symbol row col) result-row) | ||
| 3242 | (setq prev-row row)) | ||
| 3243 | (push result-row result) | ||
| 3244 | (while rest | ||
| 3245 | (let ((x (pop rest))) | ||
| 3246 | (case x | ||
| 3247 | ((>v) (setq transpose nil reorient-x nil reorient-y nil)) | ||
| 3248 | ((>^)(setq transpose nil reorient-x nil reorient-y t)) | ||
| 3249 | ((<^)(setq transpose nil reorient-x t reorient-y t)) | ||
| 3250 | ((<v)(setq transpose nil reorient-x t reorient-y nil)) | ||
| 3251 | ((v>)(setq transpose t reorient-x nil reorient-y t)) | ||
| 3252 | ((^>)(setq transpose t reorient-x nil reorient-y nil)) | ||
| 3253 | ((^<)(setq transpose t reorient-x t reorient-y nil)) | ||
| 3254 | ((v<)(setq transpose t reorient-x t reorient-y t)) | ||
| 3255 | ((* *2 *1) (setq vectorize x)) | ||
| 3256 | ((!) (setq clean 'ses--clean-!)) | ||
| 3257 | ((_) (setq clean `(lambda (&rest x) (ses--clean-_ x ,(if rest (pop rest) 0))))) | ||
| 3258 | (t | ||
| 3259 | (cond | ||
| 3260 | ; shorthands one row | ||
| 3261 | ((and (null (cddr result)) (memq x '(> <))) | ||
| 3262 | (push (intern (concat (symbol-name x) "v")) rest)) | ||
| 3263 | ; shorthands one col | ||
| 3264 | ((and (null (cdar result)) (memq x '(v ^))) | ||
| 3265 | (push (intern (concat (symbol-name x) ">")) rest)) | ||
| 3266 | (t (error "Unexpected flag `%S' in ses-range" x))))))) | ||
| 3267 | (if reorient-y | ||
| 3268 | (setcdr (last result 2) nil) | ||
| 3269 | (setq result (cdr (nreverse result)))) | ||
| 3270 | (unless reorient-x | ||
| 3271 | (setq result (mapcar 'nreverse result))) | ||
| 3272 | (when transpose | ||
| 3273 | (let ((ret (mapcar (lambda (x) (list x)) (pop result))) iter) | ||
| 3274 | (while result | ||
| 3275 | (setq iter ret) | ||
| 3276 | (dolist (elt (pop result)) | ||
| 3277 | (setcar iter (cons elt (car iter))) | ||
| 3278 | (setq iter (cdr iter)))) | ||
| 3279 | (setq result ret))) | ||
| 3280 | |||
| 3281 | (flet ((vectorize-*1 | ||
| 3282 | (clean result) | ||
| 3283 | (cons clean (cons (quote 'vec) (apply 'append result)))) | ||
| 3284 | (vectorize-*2 | ||
| 3285 | (clean result) | ||
| 3286 | (cons clean (cons (quote 'vec) (mapcar (lambda (x) | ||
| 3287 | (cons clean (cons (quote 'vec) x))) | ||
| 3288 | result))))) | ||
| 3289 | (case vectorize | ||
| 3290 | ((nil) (cons clean (apply 'append result))) | ||
| 3291 | ((*1) (vectorize-*1 clean result)) | ||
| 3292 | ((*2) (vectorize-*2 clean result)) | ||
| 3293 | ((*) (if (cdr result) | ||
| 3294 | (vectorize-*2 clean result) | ||
| 3295 | (vectorize-*1 clean result))))))) | ||
| 3183 | 3296 | ||
| 3184 | (defun ses-delete-blanks (&rest args) | 3297 | (defun ses-delete-blanks (&rest args) |
| 3185 | "Return ARGS reversed, with the blank elements (nil and *skip*) removed." | 3298 | "Return ARGS reversed, with the blank elements (nil and *skip*) removed." |