@table @kbd
@item j
-Moves point to cell, specified by identifier (@code{ses-jump}).
+Moves point to cell, specified by identifier (@code{ses-jump}). Unless
+the cell is a renamed cell, the identifier is case-insensitive. A
+prefix argument @math{n} move to cell with coordinates @math{(n\div R,
+n \% C)} for a spreadsheet of @math{R} rows and @math{C} columns, and
+A1 being of coordinates @math{(0,0)}. The way the identifier or the
+command prefix argument are interpreted can be customized through
+variables @code{ses-jump-cell-name-function} and
+@code{ses-jump-prefix-function}.
@end table
Point is always at the left edge of a cell, or at the empty endline.
@section Customizing @acronym{SES}
@cindex customizing
@vindex enable-local-eval
-@vindex ses-mode-hook
-@vindex safe-functions
-@vindex enable-local-eval
-
By default, a newly-created spreadsheet has 1 row and 1 column. The
column width is 7 and the default printer is @samp{"%.7g"}. Each of these
up or down. For diagonal movement, select two functions from the
list.
+@vindex ses-jump-cell-name-function
+@code{ses-jump-cell-name-function} is a customizable variable by
+default set to the @code{upcase} function. This function is called
+when you pass a cell name to the @command{ses-jump} command (@kbd{j}),
+it changes the entered cell name to that where to jump. The default
+setting @code{upcase} allows you to enter the cell name in low
+case. Another use of @code{ses-jump-cell-name-function} could be some
+internationalisation to convert non latin characters into latin
+equivalents to name the cell. Instead of a cell name, the function may
+return cell coordinates in the form of a cons, for instance @code{(0
+. 0)} for cell @code{A1}, @code{(1 . 0)} for cell @code{A2}, etc.
+
+@vindex ses-jump-prefix-function
+@code{ses-jump-prefix-function} is a customisable variable by default
+set to the @code{ses-jump-prefix} function. This function is called
+when you give a prefix argument to the @command{ses-jump} command
+(@kbd{j}). It returns a cell name or cell coordinates corresponding to
+the prefix argument. Cell coordinates are in the form of a cons, for
+instance @code{(1 . 0)} for cell @code{A2}. The default setting
+@code{ses-jump-prefix} will number cells left to right and then top
+down, so assuming a 4x3 spreadsheet prefix argument 0 jumps to cell
+A1, prefix argument 2 jumps to C1, prefix argument 3 jumps to A2, etc.
+
+@vindex ses-mode-hook
@code{ses-mode-hook} is a normal mode hook (list of functions to
execute when starting @acronym{SES} mode for a buffer).
+@vindex safe-functions
The variable @code{safe-functions} is a list of possibly-unsafe
functions to be treated as safe when analyzing formulas and printers.
@xref{Virus protection}. Before customizing @code{safe-functions},
:group 'ses
:type 'hook)
+(defcustom ses-jump-cell-name-function 'upcase
+ "Function to process the string passed to function ‘ses-jump’. Set it to 'identity to make no change.
+Set it to 'upcase to make cell name change case isensitive.
+
+ May return
+
+* a string, in this case this must be a cell name.
+* a (row . col) cons cell, in this case that must be valid cell coordinate."
+ :group 'ses
+ :type 'function)
+
+(defcustom ses-jump-prefix-function 'ses-jump-prefix
+ "Function that takes the prefix argument passed to function ‘ses-jump’. It may return the same
+sort of thing as ‘ses-jump-cell-name-function’."
+ :group 'ses
+ :type 'function)
+
+
;;----------------------------------------------------------------------------
;; Global variables and constants
;;----------------------------------------------------------------------------
;; Redisplay and recalculation
;;----------------------------------------------------------------------------
+(defun ses-jump-prefix (prefix-int)
+ "Convert an integer into a (ROW . COL), by numbering cells starting from 0 from top left to bottom right, going row by row."
+ (and (>= prefix-int 0)
+ (< prefix-int (* ses--numcols ses--numrows))
+ (cons (/ prefix-int ses--numcols) (% prefix-int ses--numcols))))
-(defun ses-jump (sym)
+
+(defun ses-jump (&optional sym)
"Move point to cell SYM."
- (interactive (let* (names
- (s (completing-read
- "Jump to cell: "
- (and ses--named-cell-hashmap
- (progn (maphash (lambda (key _val)
- (push (symbol-name key) names))
- ses--named-cell-hashmap)
- names)))))
- (if (string= s "")
- (user-error "Invalid cell name")
- (list (intern s)))))
- (let ((rowcol (ses-sym-rowcol sym)))
+ (interactive "P")
+ (setq sym
+ (if current-prefix-arg
+ (funcall ses-jump-prefix-function (prefix-numeric-value sym))
+ (or sym
+ (completing-read
+ "Jump to cell: "
+ (and ses--named-cell-hashmap
+ (let (names)
+ (maphash (lambda (key _val)
+ (push (symbol-name key) names))
+ ses--named-cell-hashmap)
+ names))))))
+ (and (stringp sym)
+ (not (and ses--named-cell-hashmap (gethash (intern sym) ses--named-cell-hashmap)))
+ (setq sym (funcall ses-jump-cell-name-function sym)))
+ (if (stringp sym)
+ (if (string= sym "")
+ (user-error "Empty cell name")
+ (setq sym (intern sym))))
+ (let ((rowcol (if (consp sym)
+ (prog1 sym (setq sym (ses-cell-symbol (car sym) (cdr sym))))
+ (ses-sym-rowcol sym))))
(or rowcol (error "Invalid cell name"))
(if (eq (symbol-value sym) '*skip*)
- (error "Cell is covered by preceding cell"))
+ (error "Cell is covered by preceding cell"))
(ses-goto-print (car rowcol) (cdr rowcol))))
(defun ses-jump-safe (cell)
(should (eq ses--bar 2)))))
+;; JUMP tests
+;; ======================================================================
+(ert-deftest ses-jump-B2-prefix-arg ()
+ "Test jumping to cell B2 by use of prefix argument"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ ;; C-u 4 M-x ses-jump
+ (let ((current-prefix-arg 4))
+ (call-interactively 'ses-jump))
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+
+(ert-deftest ses-jump-B2-lowcase ()
+ "Test jumping to cell B2 by use of lowcase cell name string"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (funcall-interactively 'ses-jump "b2")
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-lowcase-keys ()
+ "Test jumping to cell B2 by use of lowcase cell name string with simulating keys"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (ert-simulate-keys [ ?b ?2 return] (ses-jump))
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-symbol ()
+ "Test jumping to cell B2 by use of cell name symbol"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (funcall-interactively 'ses-jump 'B2)
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-renamed ()
+ "Test jumping to cell B2 after renaming it `ses--toto'."
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (ses-rename-cell 'ses--toto (ses-get-cell 1 1))
+ (ses-jump 'ses--toto)
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'ses--toto)))))
+
(provide 'ses-tests)
;;; ses-tests.el ends here