aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Belaïche2012-11-09 06:48:05 +0100
committerVincent Belaïche2012-11-09 06:48:05 +0100
commit93a66b3a3d1b1d19da6d3e759ebe4b9192c70efc (patch)
tree35c63f86419899ea7c50cc220cba17376ffd712b
parent57618ecf3358e49ab3c380330e82ca8d2078cc63 (diff)
downloademacs-93a66b3a3d1b1d19da6d3e759ebe4b9192c70efc.tar.gz
emacs-93a66b3a3d1b1d19da6d3e759ebe4b9192c70efc.zip
* ses.el: Use hash map for getting named cells coordinates.
symbol to coordinate mapping is made by symbol property `ses-cell'. This means that the same mapping is done for all SES sheets. That is good enough for cells with standard A1 names, but not for named cell. So a hash map is added for those latter. (defconst ses-localvars): added local variable ses--named-cell-hashmap (ses-sym-rowcol): Use hashmap for named cell. (ses-is-cell-sym-p): New defun. (ses-decode-cell-symbol): New defun. (ses-create-cell-variable): Add cell to hashmap when name is not A1-like. (ses-rename-cell): Check that cell new name is not already in spreadsheet with the use of ses-is-cell-sym-p (ses-rename-cell): Use hash map for named cells, but accept also renaming back to A1-like.
-rw-r--r--lisp/ChangeLog17
-rw-r--r--lisp/ses.el92
2 files changed, 87 insertions, 22 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index f0af63ac094..d7cb2143d36 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,20 @@
12012-11-09 Vincent Belaïche <vincentb1@users.sourceforge.net>
2
3 * ses.el: symbol to coordinate mapping is made by symbol property
4 `ses-cell'. This means that the same mapping is done for all SES
5 sheets. That is good enough for cells with standard A1 names, but
6 not for named cell. So a hash map is added for those
7 latter.
8 (defconst ses-localvars): added local variable ses--named-cell-hashmap
9 (ses-sym-rowcol): Use hashmap for named cell.
10 (ses-is-cell-sym-p): New defun.
11 (ses-decode-cell-symbol): New defun.
12 (ses-create-cell-variable): Add cell to hashmap when name is not A1-like.
13 (ses-rename-cell): Check that cell new name is not already in
14 spreadsheet with the use of ses-is-cell-sym-p
15 (ses-rename-cell): Use hash map for named cells, but accept also
16 renaming back to A1-like.
17
12012-11-09 Stefan Monnier <monnier@iro.umontreal.ca> 182012-11-09 Stefan Monnier <monnier@iro.umontreal.ca>
2 19
3 * emacs-lisp/advice.el: Use new dynamic docstrings. 20 * emacs-lisp/advice.el: Use new dynamic docstrings.
diff --git a/lisp/ses.el b/lisp/ses.el
index 7cdac74e310..27b906d22e3 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -278,6 +278,7 @@ default printer and then modify its output.")
278 ses--default-printer 278 ses--default-printer
279 ses--deferred-narrow ses--deferred-recalc 279 ses--deferred-narrow ses--deferred-recalc
280 ses--deferred-write ses--file-format 280 ses--deferred-write ses--file-format
281 ses--named-cell-hashmap
281 (ses--header-hscroll . -1) ; Flag for "initial recalc needed" 282 (ses--header-hscroll . -1) ; Flag for "initial recalc needed"
282 ses--header-row ses--header-string ses--linewidth 283 ses--header-row ses--header-string ses--linewidth
283 ses--numcols ses--numrows ses--symbolic-formulas 284 ses--numcols ses--numrows ses--symbolic-formulas
@@ -511,9 +512,22 @@ PROPERTY-NAME."
511 `(aref ses--col-printers ,col)) 512 `(aref ses--col-printers ,col))
512 513
513(defmacro ses-sym-rowcol (sym) 514(defmacro ses-sym-rowcol (sym)
514 "From a cell-symbol SYM, gets the cons (row . col). A1 => (0 . 0). 515 "From a cell-symbol SYM, gets the cons (row . col). A1 => (0 . 0). Result
515Result is nil if SYM is not a symbol that names a cell." 516is nil if SYM is not a symbol that names a cell."
516 `(and (symbolp ,sym) (get ,sym 'ses-cell))) 517 `(let ((rc (and (symbolp ,sym) (get ,sym 'ses-cell))))
518 (if (eq rc :ses-named)
519 (gethash ,sym ses--named-cell-hashmap)
520 rc)))
521
522(defun ses-is-cell-sym-p (sym)
523 "Check whether SYM point at a cell of this spread sheet."
524 (let ((rowcol (get sym 'ses-cell)))
525 (and rowcol
526 (if (eq rowcol :ses-named)
527 (and ses--named-cell-hashmap (gethash sym ses--named-cell-hashmap))
528 (and (< (car rowcol) ses--numrows)
529 (< (cdr rowcol) ses--numcols)
530 (eq (ses-cell-symbol (car rowcol) (cdr rowcol)) sym))))))
517 531
518(defmacro ses-cell (sym value formula printer references) 532(defmacro ses-cell (sym value formula printer references)
519 "Load a cell SYM from the spreadsheet file. Does not recompute VALUE from 533 "Load a cell SYM from the spreadsheet file. Does not recompute VALUE from
@@ -682,6 +696,28 @@ for this spreadsheet."
682 "Produce a symbol that names the cell (ROW,COL). (0,0) => 'A1." 696 "Produce a symbol that names the cell (ROW,COL). (0,0) => 'A1."
683 (intern (concat (ses-column-letter col) (number-to-string (1+ row))))) 697 (intern (concat (ses-column-letter col) (number-to-string (1+ row)))))
684 698
699(defun ses-decode-cell-symbol (str)
700 "Decode a symbol \"A1\" => (0,0). Returns `nil' if STR is not a
701 canonical cell name. Does not save match data."
702 (let (case-fold-search)
703 (and (string-match "\\`\\([A-Z]+\\)\\([0-9]+\\)\\'" str)
704 (let* ((col-str (match-string-no-properties 1 str))
705 (col 0)
706 (col-offset 0)
707 (col-base 1)
708 (col-idx (1- (length col-str)))
709 (row (1- (string-to-number (match-string-no-properties 2 str)))))
710 (and (>= row 0)
711 (progn
712 (while
713 (progn
714 (setq col (+ col (* (- (aref col-str col-idx) ?A) col-base))
715 col-base (* col-base 26)
716 col-idx (1- col-idx))
717 (and (>= col-idx 0)
718 (setq col (+ col col-base)))))
719 (cons row col)))))))
720
685(defun ses-create-cell-variable-range (minrow maxrow mincol maxcol) 721(defun ses-create-cell-variable-range (minrow maxrow mincol maxcol)
686 "Create buffer-local variables for cells. This is undoable." 722 "Create buffer-local variables for cells. This is undoable."
687 (push `(apply ses-destroy-cell-variable-range ,minrow ,maxrow ,mincol ,maxcol) 723 (push `(apply ses-destroy-cell-variable-range ,minrow ,maxrow ,mincol ,maxcol)
@@ -704,7 +740,11 @@ row and column of the cell, with numbering starting from 0.
704Return nil in case of failure." 740Return nil in case of failure."
705 (unless (local-variable-p sym) 741 (unless (local-variable-p sym)
706 (make-local-variable sym) 742 (make-local-variable sym)
707 (put sym 'ses-cell (cons row col)))) 743 (if (let (case-fold-search) (string-match "\\`[A-Z]+[0-9]+\\'" (symbol-name sym)))
744 (put sym 'ses-cell (cons row col))
745 (put sym 'ses-cell :ses-named)
746 (setq ses--named-cell-hashmap (or ses--named-cell-hashmap (make-hash-table :test 'eq)))
747 (puthash sym (cons row col) ses--named-cell-hashmap))))
708 748
709;; We do not delete the ses-cell properties for the cell-variables, in 749;; We do not delete the ses-cell properties for the cell-variables, in
710;; case a formula that refers to this cell is in the kill-ring and is 750;; case a formula that refers to this cell is in the kill-ring and is
@@ -3211,27 +3251,36 @@ highlighted range in the spreadsheet."
3211(defun ses-rename-cell (new-name &optional cell) 3251(defun ses-rename-cell (new-name &optional cell)
3212 "Rename current cell." 3252 "Rename current cell."
3213 (interactive "*SEnter new name: ") 3253 (interactive "*SEnter new name: ")
3214 (and (local-variable-p new-name) 3254 (or
3215 (ses-sym-rowcol new-name) 3255 (and (local-variable-p new-name)
3216 ;; this test is needed because ses-cell property of deleted cells 3256 (ses-is-cell-sym-p new-name)
3217 ;; is not deleted in case of subsequent undo 3257 (error "Already a cell name"))
3218 (memq new-name ses--renamed-cell-symb-list) 3258 (and (boundp new-name)
3219 (error "Already a cell name")) 3259 (null (yes-or-no-p (format "`%S' is already bound outside this buffer, continue? "
3220 (and (boundp new-name) 3260 new-name)))
3221 (null (yes-or-no-p (format "`%S' is already bound outside this buffer, continue? " 3261 (error "Already a bound cell name")))
3222 new-name))) 3262 (let* (curcell
3223 (error "Already a bound cell name")) 3263 (sym (if (ses-cell-p cell)
3224 (let* ((sym (if (ses-cell-p cell)
3225 (ses-cell-symbol cell) 3264 (ses-cell-symbol cell)
3226 (setq cell nil) 3265 (setq cell nil
3266 curcell t)
3227 (ses-check-curcell) 3267 (ses-check-curcell)
3228 ses--curcell)) 3268 ses--curcell))
3229 (rowcol (ses-sym-rowcol sym)) 3269 (rowcol (ses-sym-rowcol sym))
3230 (row (car rowcol)) 3270 (row (car rowcol))
3231 (col (cdr rowcol))) 3271 (col (cdr rowcol))
3232 (setq cell (or cell (ses-get-cell row col))) 3272 new-rowcol old-name)
3233 (push `(ses-rename-cell ,(ses-cell-symbol cell) ,cell) buffer-undo-list) 3273 (setq cell (or cell (ses-get-cell row col))
3234 (put new-name 'ses-cell rowcol) 3274 old-name (ses-cell-symbol cell)
3275 new-rowcol (ses-decode-cell-symbol (symbol-name new-name)))
3276 (if new-rowcol
3277 (if (equal new-rowcol rowcol)
3278 (put new-name 'ses-cell rowcol)
3279 (error "Not a valid name for this cell location"))
3280 (setq ses--named-cell-hashmap (or ses--named-cell-hashmap (make-hash-table :test 'eq)))
3281 (put new-name 'ses-cell :ses-named)
3282 (puthash new-name rowcol ses--named-cell-hashmap))
3283 (push `(ses-rename-cell ,old-name ,cell) buffer-undo-list)
3235 ;; replace name by new name in formula of cells refering to renamed cell 3284 ;; replace name by new name in formula of cells refering to renamed cell
3236 (dolist (ref (ses-cell-references cell)) 3285 (dolist (ref (ses-cell-references cell))
3237 (let* ((x (ses-sym-rowcol ref)) 3286 (let* ((x (ses-sym-rowcol ref))
@@ -3251,9 +3300,8 @@ highlighted range in the spreadsheet."
3251 (push new-name ses--renamed-cell-symb-list) 3300 (push new-name ses--renamed-cell-symb-list)
3252 (set new-name (symbol-value sym)) 3301 (set new-name (symbol-value sym))
3253 (aset cell 0 new-name) 3302 (aset cell 0 new-name)
3254 (put sym 'ses-cell nil)
3255 (makunbound sym) 3303 (makunbound sym)
3256 (setq sym new-name) 3304 (and curcell (setq ses--curcell new-name))
3257 (let* ((pos (point)) 3305 (let* ((pos (point))
3258 (inhibit-read-only t) 3306 (inhibit-read-only t)
3259 (col (current-column)) 3307 (col (current-column))