]> git.eshelyaron.com Git - emacs.git/commitdiff
SES with case insensitive cell names for jumping.
authorVincent Belaïche <vincentb1@users.sourceforge.net>
Mon, 4 Apr 2022 17:42:07 +0000 (19:42 +0200)
committerVincent Belaïche <vincentb1@users.sourceforge.net>
Mon, 4 Apr 2022 17:42:07 +0000 (19:42 +0200)
* doc/misc/ses.texi (The Basics): Document that ses-jump may be
customized.
(Customizing @acronym{SES}): Document new customisations for ses-jump.

* lisp/ses.el (ses-jump-cell-name-function)
(ses-jump-prefix-function): New defcustoms.
(ses-jump-prefix): New defun.
(ses-jump): Make ses-jump use the new defcustoms.

* test/lisp/ses-tests.el (ses-jump-B2-prefix-arg)
(ses-jump-B2-lowcase, ses-jump-B2-lowcase-keys)
(ses-jump-B2-symbol, ses-jump-B2-renamed): New tests.

doc/misc/ses.texi
lisp/ses.el
test/lisp/ses-tests.el

index 0acb7bf3f15381d586294a6f2685512eb9b13ba9..6d0415cdbbb4e1237539ff27bff477dec1d8940f 100644 (file)
@@ -220,7 +220,14 @@ You move around with the regular Emacs movement commands.
 
 @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.
@@ -726,10 +733,6 @@ yank.  This doesn't make any difference?
 @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
@@ -740,9 +743,34 @@ cell.  You can customize @code{ses-after-entry-functions} to move left or
 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},
index 45e323e8051bf0b90ab386bc1ef940468c2d3489..e3b3a45776b1ab3fc46f5354ed2a5b0b4cc3dd04 100644 (file)
@@ -112,6 +112,24 @@ Each function is called with ARG=1."
   :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
@@ -2233,24 +2251,41 @@ Based on the current set of columns and `window-hscroll' position."
 ;;----------------------------------------------------------------------------
 ;; 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)
index cd524cbf6e076c835b4c92100337608b85f56f16..b60ddeea78e105d6ad6baf7b06b8a4ff4b6c5e04 100644 (file)
@@ -178,6 +178,61 @@ to `ses--bar' and inserting a row, makes A2 value empty, and `ses--bar' equal to
       (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