From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: =?iso-8859-1?Q?Vincent_Bela=EFche?= Newsgroups: gmane.emacs.devel Subject: Contribution to SES (resend) Date: Thu, 22 Apr 2010 08:52:51 +0200 Message-ID: <80ochc3rng.fsf@gmail.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: dough.gmane.org 1271919425 8838 80.91.229.12 (22 Apr 2010 06:57:05 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 22 Apr 2010 06:57:05 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Apr 22 08:57:04 2010 connect(): No such file or directory Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1O4qLP-0005nV-4E for ged-emacs-devel@m.gmane.org; Thu, 22 Apr 2010 08:57:03 +0200 Original-Received: from localhost ([127.0.0.1]:59522 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O4qLO-00034e-DV for ged-emacs-devel@m.gmane.org; Thu, 22 Apr 2010 02:57:02 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O4qLI-00034Z-NC for emacs-devel@gnu.org; Thu, 22 Apr 2010 02:56:56 -0400 Original-Received: from [140.186.70.92] (port=59517 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O4qL7-00034A-WF for emacs-devel@gnu.org; Thu, 22 Apr 2010 02:56:56 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O4qKz-0003Qj-Rx for emacs-devel@gnu.org; Thu, 22 Apr 2010 02:56:45 -0400 Original-Received: from smtp2e.orange.fr ([80.12.242.113]:27304) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O4qKv-0003Pp-SO for emacs-devel@gnu.org; Thu, 22 Apr 2010 02:56:37 -0400 Original-Received: from me-wanadoo.net (localhost [127.0.0.1]) by mwinf2e24.orange.fr (SMTP Server) with ESMTP id 14CD18000150 for ; Thu, 22 Apr 2010 08:56:33 +0200 (CEST) Original-Received: from me-wanadoo.net (localhost [127.0.0.1]) by mwinf2e24.orange.fr (SMTP Server) with ESMTP id 087A980003D6 for ; Thu, 22 Apr 2010 08:56:33 +0200 (CEST) Original-Received: from CHOUNEK (ARennes-353-1-61-96.w92-139.abo.wanadoo.fr [92.139.100.96]) by mwinf2e24.orange.fr (SMTP Server) with ESMTP id 7F8DB8000150 for ; Thu, 22 Apr 2010 08:56:32 +0200 (CEST) X-ME-UUID: 20100422065632522.7F8DB8000150@mwinf2e24.orange.fr X-Antivirus: avast! (VPS 100421-1, 21/04/2010), Outbound message X-Antivirus-Status: Clean X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:124014 Archived-At: Dear all, I would like to make a contribution to SES, a user of which I am. Here is the Change log which I propose: --8<-------------coupez ici--------------d=C3=A9but-------------->8--- 2010-04-22 Vincent Bela=C3=AFche * ses.el (ses-list): Addition of the ses-list macro in order to have more flexibility for range building. This also makes `ses+' kind of obsolete as `(apply 'ses+ (ses-range A1 A5))' can be replaced by `(apply '+ (ses-list A1 A5 !))' which is more universal as you could have anything instead of `+'. --8<-------------coupez ici---------------fin--------------->8--- And here is a diff -c old new of ses.el: --8<-------------coupez ici--------------d=C3=A9but-------------->8--- *** ses.el.old Wed Apr 21 21:34:40 2010 --- ses.el Thu Apr 22 06:47:27 2010 *************** *** 141,146 **** --- 141,147 ---- (defconst ses-mode-edit-map (let ((keys '("\C-c\C-r" ses-insert-range "\C-c\C-s" ses-insert-ses-range + "\C-c\C-v" ses-insert-ses-list [S-mouse-3] ses-insert-range-click [C-S-mouse-3] ses-insert-ses-range-click "\M-\C-i" lisp-complete-symbol)) *************** *** 1085,1091 **** ((ses-sym-rowcol cur) ;;Save this reference (add-to-list 'result-so-far cur)) ! ((eq (car-safe cur) 'ses-range) ;;All symbols in range are referenced (dolist (x (cdr (macroexpand cur))) (add-to-list 'result-so-far x))) --- 1086,1092 ---- ((ses-sym-rowcol cur) ;;Save this reference (add-to-list 'result-so-far cur)) ! ((memq (car-safe cur) '(ses-list ses-range)) ;;All symbols in range are referenced (dolist (x (cdr (macroexpand cur))) (add-to-list 'result-so-far x))) *************** *** 1144,1150 **** ;;implies 'delete. (unless ses-relocate-return (setq ses-relocate-return 'delete)))) ! ((eq (car-safe cur) 'ses-range) (setq cur (ses-relocate-range cur startrow startcol rowincr colincr)) (if cur (push cur result))) --- 1145,1151 ---- ;;implies 'delete. (unless ses-relocate-return (setq ses-relocate-return 'delete)))) ! ((memq (car-safe cur) '(ses-list ses-range)) (setq cur (ses-relocate-range cur startrow startcol rowincr colincr)) (if cur (push cur result))) *************** *** 1159,1175 **** (nreverse result)))) =20=20 (defun ses-relocate-range (range startrow startcol rowincr colincr) ! "Relocate one RANGE, of the form '(ses-range min max). Cells starting ! at (STARTROW,STARTCOL) are being shifted by (ROWINCR,COLINCR). Result is= the ! new range, or nil if the entire range is deleted. If new rows are being = added ! just beyond the end of a row range, or new columns just beyond a column r= ange, ! the new rows/columns will be added to the range. Sets `ses-relocate-retu= rn' ! if the range was altered." (let* ((minorig (cadr range)) (minrowcol (ses-sym-rowcol minorig)) (min (ses-relocate-symbol minorig minrowcol startrow startcol rowincr colincr)) (maxorig (nth 2 range)) (maxrowcol (ses-sym-rowcol maxorig)) (max (ses-relocate-symbol maxorig maxrowcol --- 1160,1179 ---- (nreverse result)))) =20=20 (defun ses-relocate-range (range startrow startcol rowincr colincr) ! "Relocate one RANGE, of the form '(ses-range min max) or ! '(ses-list min max ...). Cells starting at (STARTROW,STARTCOL) ! are being shifted by (ROWINCR,COLINCR). Result is the new range, ! or nil if the entire range is deleted. If new rows are being ! added just beyond the end of a row range, or new columns just ! beyond a column range, the new rows/columns will be added to the ! range. Sets `ses-relocate-return' if the range was altered." (let* ((minorig (cadr range)) (minrowcol (ses-sym-rowcol minorig)) (min (ses-relocate-symbol minorig minrowcol startrow startcol rowincr colincr)) + (rest (cdddr range)) + (fun (car range)) (maxorig (nth 2 range)) (maxrowcol (ses-sym-rowcol maxorig)) (max (ses-relocate-symbol maxorig maxrowcol *************** *** 1228,1234 **** (funcall field (ses-sym-rowcol min)))) ;;This range has changed size (setq ses-relocate-return 'range)) ! (list 'ses-range min max)))) =20=20 (defun ses-relocate-all (minrow mincol rowincr colincr) "Alter all cell values, symbols, formulas, and reference-lists to reloc= ate --- 1232,1238 ---- (funcall field (ses-sym-rowcol min)))) ;;This range has changed size (setq ses-relocate-return 'range)) ! `( ,fun ,min ,max @,rest)))) =20=20 (defun ses-relocate-all (minrow mincol rowincr colincr) "Alter all cell values, symbols, formulas, and reference-lists to reloc= ate *************** *** 2823,2841 **** ,(cdr ses--curcell)))))) (insert (substring (prin1-to-string (nreverse x)) 1 -1)))) =20=20 ! (defun ses-insert-ses-range () ! "Inserts \"(ses-range x y)\" in the minibuffer to represent the current= ly ! highlighted range in the spreadsheet." ! (interactive "*") (let (x) (with-current-buffer (window-buffer minibuffer-scroll-window) (ses-command-hook) ;For ses-coverage (ses-check-curcell 'needrange) ! (setq x (format "(ses-range %S %S)" (car ses--curcell) (cdr ses--curcell)))) (insert x))) =20=20 (defun ses-insert-range-click (event) "Mouse version of `ses-insert-range'." (interactive "*e") --- 2827,2859 ---- ,(cdr ses--curcell)))))) (insert (substring (prin1-to-string (nreverse x)) 1 -1)))) =20=20 ! (defun ses--insert-ses-range-or-ses-list (to-be-inserted) ! "Insert \"(ses-range x y)\" or \"(ses-list x y)\" into the ! minibuffer depending on TO-BE-INSERTED being equal to \"range\" ! or to \"list\"." (let (x) (with-current-buffer (window-buffer minibuffer-scroll-window) (ses-command-hook) ;For ses-coverage (ses-check-curcell 'needrange) ! (setq x (format "(ses-%s %S %S)" ! to-be-inserted (car ses--curcell) (cdr ses--curcell)))) (insert x))) =20=20 + (defun ses-insert-ses-range () + "Inserts \"(ses-range x y)\" in the minibuffer to represent the current= ly + highlighted range in the spreadsheet." + (interactive "*") + (ses--insert-ses-range-or-ses-list "range")) +=20 + (defun ses-insert-ses-list () + "Inserts \"(ses-list x y)\" in the minibuffer to represent the currently + highlighted range in the spreadsheet." + (interactive "*") + (ses--insert-ses-range-or-ses-list "list")) +=20 +=20 (defun ses-insert-range-click (event) "Mouse version of `ses-insert-range'." (interactive "*e") *************** *** 2890,2901 **** "Expands to a list of cell-symbols for the range. The range automatica= lly expands to include any new row or column inserted into its middle. The S= ES library code specifically looks for the symbol `ses-range', so don't crea= te an ! alias for this macro!" (let (result) (ses-dorange (cons from to) (push (ses-cell-symbol row col) result)) (cons 'list result))) =20=20 (defun ses-delete-blanks (&rest args) "Return ARGS reversed, with the blank elements (nil and *skip*) removed= ." (let (result) --- 2908,3030 ---- "Expands to a list of cell-symbols for the range. The range automatica= lly expands to include any new row or column inserted into its middle. The S= ES library code specifically looks for the symbol `ses-range', so don't crea= te an ! alias for this macro! !=20 ! Cells are listed in reverse order, that is to say from TO up to ! FROM, for instance `(ses-range A1 B2)' will produce (B2 B1 A2 ! A1). This is important to know if you make a formula like `(apply ! '- (ses-range A1 A5))'." (let (result) (ses-dorange (cons from to) (push (ses-cell-symbol row col) result)) (cons 'list result))) =20=20 + (defun ses--clean-! (&rest x) + "Clean by delq list X from any occurrence of `nil' or `*skip*'" + (delq nil (delq '*skip* x))) +=20 + (defun ses--clean-!x (x y) + "Clean list X by replacing by Y any occurrence of `nil' or `*skip*'. + This will change X by making setcar on its cons cells." + (let ((ret x) ret-elt) + (while ret + (setq ret-elt (car ret)) + (when (memq ret-elt '(nil *skip*)) + (setcar ret y)) + (setq ret (cdr ret)))) + x) +=20 + (defsubst ses--clean-!0 (&rest x)=20 + "Clean list X by replacing by 0 any occurrence of `nil' or `*skip*'. + This will change X by making setcar on its cons cells." + (ses--clean-!x x 0)) + (defsubst ses--clean-!. (&rest x)=20 + "Clean list X by replacing by \"\" any occurrence of `nil' or `*skip*'. + This will change X by making setcar on its cons cells." + (ses--clean-!x x "")) +=20 + (defmacro ses-list (from to &rest rest) + "Expands to a list of cell-symbols for the range groing from + FROM up to TO. The range automatically expands to include any + new row or column inserted into its middle. The SES library code + specifically looks for the symbol `ses-list', so don't create an + alias for this macro! +=20 + By passing in REST some flags one can configure the way the range + is read and how it is formatted.=20 +=20 + In the sequel we assume that cells A1, B1, A2 B2 have respective values + 1 2 3 and 4 for examplication. +=20 + A `>v' (default) `>^', `', `v<', `^>', `^<' flag + will configure the order of browsing through the range. This + way `(ses-list A1 B2 ^>)' will evaluate to `(1 3 2 4)', + while `(ses-list A1 B2 >^)' will evaluate to (3 4 1 2). +=20 + A `!' flag will remove all cells whose value is nil or `*skip*' + while `!0' will replace them by 0, and `!.' will replace them by + \"\". +=20 + A `*', `*1' or `*2' flag will vectorize the range in the sense of + Calc. See info node `(Calc) Top'. Flag `*' will output either a + vector or a matrix depending on the number of rows, `*1' will + flatten the result to a one row vector, and `*2' will make a + matrix whatever the number of rows.=20 +=20 + Warning: interaction with Calc is expermimental and may produce + confusing results if you are not aware of Calc data format. Use + `math-format-value' as a printer for Calc objects." + (let (result-row result (prev-row -1) + reorient-x reorient-y transpose vectorize=20 + (clean 'list)) + (ses-dorange (cons from to) + (when (/=3D prev-row row) + (push result-row result) + (setq result-row nil)) + (push (ses-cell-symbol row col) result-row) + (setq prev-row row)) + (push result-row result) + (dolist (x rest) + (let ((s (assq x `((>v setq transpose nil reorient-x nil reorient-= y nil) + (>^ setq transpose nil reorient-x nil reorient-y t)=20 + (<^ setq transpose nil reorient-x t reorient-y t)=20 + ( setq transpose t reorient-x nil reorient-y t)=20=20=20=20=20 + (^> setq transpose t reorient-x nil reorient-y nil)=20=20=20 + (^< setq transpose t reorient-x t reorient-y nil)=20 + (v< setq transpose t reorient-x t reorient-y t)=20=20=20 + (* . #1=3D(setq vectorize x)) + (*2 . #1#) + (*1 . #1#) + (! setq clean 'ses--clean-!) + (!0 setq clean 'ses--clean-!0) + (!. setq clean 'ses--clean-!\.) )))) + (if s (eval (cdr s)) + (error "Unexpected flag `%S' in ses-list" x)))) +=20 + (if reorient-y=20 + (setcdr (last result 2) nil) + (setq result (cdr (nreverse result)))) + (unless reorient-x + (setq result (mapcar 'nreverse result))) + (when transpose + (let ((ret (mapcar (lambda (x) (list x)) (pop result))) iter) + (while result + (setq iter ret) + (dolist (elt (pop result)) + (setcar iter (cons elt (car iter))) + (setq iter (cdr iter)))) + (setq result ret))) +=20 + (eval (cdr (assq vectorize + '((nil cons clean (apply 'append result)) + (*1 . #2=3D(cons clean (cons (quote 'vec) (apply 'append result)= ))) + (*2 . #3=3D(cons clean (cons (quote 'vec) (mapcar (lambda (x)=20 + (cons clean (cons (quote 'vec) x))) + result)))) + (* if (cdr result) #3# #2#))))))) +=20 +=20 (defun ses-delete-blanks (&rest args) "Return ARGS reversed, with the blank elements (nil and *skip*) removed= ." (let (result) *************** *** 2932,2938 **** (cons 'list result))) =20=20 ;;All standard formulas are safe ! (dolist (x '(ses-cell-value ses-range ses-delete-blanks ses+ ses-average ses-select)) (put x 'side-effect-free t)) =20=20 --- 3061,3067 ---- (cons 'list result))) =20=20 ;;All standard formulas are safe ! (dolist (x '(ses-cell-value ses-range ses-list ses-delete-blanks ses+ ses= -average ses-select)) (put x 'side-effect-free t)) =20=20 --8<-------------coupez ici---------------fin--------------->8--- Very best regards, Vincent.