unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#45917: [PATCH] Use big brackets in Calc in big mode
@ 2021-01-16 17:10 Mattias Engdegård
  2021-01-19  5:37 ` Lars Ingebrigtsen
  0 siblings, 1 reply; 5+ messages in thread
From: Mattias Engdegård @ 2021-01-16 17:10 UTC (permalink / raw)
  To: 45917

[-- Attachment #1: Type: text/plain, Size: 877 bytes --]

The attached patch makes Calc use big brackets in Big mode when the Unicode characters are available. This makes for prettier display which is sort of the point of using Big mode. It follows previous use of Unicode characters for square root and integral signs.

The code supports big versions of round, square and curly brackets. Big square brackets are currently only used for intervals and curly ones not at all (maybe they could be put to use for Stirling numbers of the second kind).

Matrices do not use big brackets but they probably should since it is standard mathematical notation.

As far as I can tell the only reasons for not applying this would be that it is common with fonts or terminals where this doesn't look good, or that the resulting formula isn't recognised by the embedded-mode parser (which is already the case with several other constructs).


[-- Attachment #2: 0001-Calc-use-big-Unicode-brackets-in-Big-mode-when-avail.patch --]
[-- Type: application/octet-stream, Size: 15245 bytes --]

From 01a065dfb6047e0c0db7a89f6113723a1763bd2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Sat, 16 Jan 2021 17:30:57 +0100
Subject: [PATCH] Calc: use big Unicode brackets in Big mode when available

* lisp/calc/calccomp.el (math--big-bracket-alist)
(math--big-bracket, math--comp-bracket, math--comp-round-bracket):
New.
(math-compose-expr, math-compose-log, math-compose-log10)
(math-compose-choose, math-compose-integ, math-compose-sum)
(math-compose-prod): Use big brackets when available.
---
 lisp/calc/calccomp.el | 247 +++++++++++++++++++++++++++---------------
 1 file changed, 162 insertions(+), 85 deletions(-)

diff --git a/lisp/calc/calccomp.el b/lisp/calc/calccomp.el
index 07e70cad0a..5f38ee71c7 100644
--- a/lisp/calc/calccomp.el
+++ b/lisp/calc/calccomp.el
@@ -138,19 +138,19 @@ math-compose-expr
 				      (math-format-number (nth 2 aa))))))
 		  (if (= calc-number-radix 10)
 		      c
-		    (list 'horiz "(" c
-			  (list 'subscr ")"
-				(int-to-string calc-number-radix)))))
+                    (list 'subscr (math--comp-round-bracket c)
+			  (int-to-string calc-number-radix))))
 	      (math-format-number a)))
 	(if (not (eq calc-language 'big))
 	    (math-format-number a prec)
 	  (if (memq (car-safe a) '(cplx polar))
 	      (if (math-zerop (nth 2 a))
 		  (math-compose-expr (nth 1 a) prec)
-		(list 'horiz "("
-		      (math-compose-expr (nth 1 a) 0)
-		      (if (eq (car a) 'cplx) ", " "; ")
-		      (math-compose-expr (nth 2 a) 0) ")"))
+                (math--comp-round-bracket
+		 (list 'horiz
+		       (math-compose-expr (nth 1 a) 0)
+		       (if (eq (car a) 'cplx) ", " "; ")
+		       (math-compose-expr (nth 2 a) 0))))
 	    (if (or (= calc-number-radix 10)
 		    (not (Math-realp a))
 		    (and calc-group-digits
@@ -340,12 +340,13 @@ math-compose-expr
               (funcall spfn a prec)
             (math-compose-var a)))))
      ((eq (car a) 'intv)
-      (list 'horiz
-            (if (memq (nth 1 a) '(0 1)) "(" "[")
-	    (math-compose-expr (nth 2 a) 0)
-            " .. "
-	    (math-compose-expr (nth 3 a) 0)
-            (if (memq (nth 1 a) '(0 2)) ")" "]")))
+      (math--comp-bracket
+       (if (memq (nth 1 a) '(0 1)) ?\( ?\[)
+       (if (memq (nth 1 a) '(0 2)) ?\) ?\])
+       (list 'horiz
+	     (math-compose-expr (nth 2 a) 0)
+             " .. "
+	     (math-compose-expr (nth 3 a) 0))))
      ((eq (car a) 'date)
       (if (eq (car calc-date-format) 'X)
 	  (math-format-date a)
@@ -377,7 +378,7 @@ math-compose-expr
 		    (and (eq (car-safe (nth 1 a)) 'cplx)
 			 (math-negp (nth 1 (nth 1 a)))
 			 (eq (nth 2 (nth 1 a)) 0)))
-		(list 'horiz "(" (math-compose-expr (nth 1 a) 0) ")")
+                (math--comp-round-bracket (math-compose-expr (nth 1 a) 0))
 	      (math-compose-expr (nth 1 a) 201))
 	    (let ((calc-language 'flat)
 		  (calc-number-radix 10)
@@ -444,7 +445,7 @@ math-compose-expr
 	(if (> prec (nth 2 a))
             (if (setq spfn (get calc-language 'math-big-parens))
                 (list 'horiz (car spfn) c (cdr spfn))
-              (list 'horiz "(" c ")"))
+              (math--comp-round-bracket c))
 	  c)))
      ((and (eq (car a) 'calcFunc-choriz)
 	   (not (eq calc-language 'unform))
@@ -612,7 +613,7 @@ math-compose-expr
 			   (list 'horiz "{left ( "
 				 (math-compose-expr a -1)
 				 " right )}")))
-		     (list 'horiz "(" (math-compose-expr a 0) ")"))))
+                     (math--comp-round-bracket (math-compose-expr a 0)))))
 		((and (memq calc-language '(tex latex))
 		      (memq (car a) '(/ calcFunc-choose calcFunc-evalto))
 		      (>= prec 0))
@@ -638,7 +639,7 @@ math-compose-expr
 			(rhs (math-compose-expr (nth 2 a) (nth 3 op) (eq (nth 1 op) '/))))
 		   (and (equal (car op) "^")
 			(eq (math-comp-first-char lhs) ?-)
-			(setq lhs (list 'horiz "(" lhs ")")))
+			(setq lhs (math--comp-round-bracket lhs)))
 		   (and (memq calc-language '(tex latex))
 			(or (equal (car op) "^") (equal (car op) "_"))
 			(not (and (stringp rhs) (= (length rhs) 1)))
@@ -721,7 +722,7 @@ math-compose-expr
 			   (list 'horiz "{left ( "
 				 (math-compose-expr a -1)
 				 " right )}")))
-		     (list 'horiz "(" (math-compose-expr a 0) ")"))))
+		     (math--comp-round-bracket (math-compose-expr a 0)))))
 		(t
 		 (let ((lhs (math-compose-expr (nth 1 a) (nth 2 op))))
 		 (list 'horiz
@@ -759,7 +760,7 @@ math-compose-expr
 			   (list 'horiz "{left ( "
 				 (math-compose-expr a -1)
 				 " right )}")))
-		     (list 'horiz "(" (math-compose-expr a 0) ")"))))
+		     (math--comp-round-bracket (math-compose-expr a 0)))))
 		(t
 		 (let ((rhs (math-compose-expr (nth 1 a) (nth 3 op))))
 		   (list 'horiz
@@ -966,6 +967,69 @@ math-tex-expr-is-flat
       (and (memq (car a) '(^ calcFunc-subscr))
 	   (math-tex-expr-is-flat (nth 1 a)))))
 
+;; FIXME: maybe try box drawing chars if big bracket chars are unavailable,
+;; like  ┌     ┐n
+;;       │a + b│     ┌ a + b ┐n
+;;       │-----│  or │ ----- │    ?
+;;       │  c  │     └   c   ┘
+;;       └     ┘
+;; They are more common than the chars below, but look a bit square.
+;; Rounded corners exist but are less commonly available.
+
+(defconst math--big-bracket-alist
+  '((?\( . (?⎛ ?⎝ ?⎜))
+    (?\) . (?⎞ ?⎠ ?⎟))
+    (?\[ . (?⎡ ?⎣ ?⎢))
+    (?\] . (?⎤ ?⎦ ?⎥))
+    (?\{ . (?⎧ ?⎩ ?⎪ ?⎨))
+    (?\} . (?⎫ ?⎭ ?⎪ ?⎬)))
+  "Alist mapping bracket chars to (UPPER LOWER EXTENSION MIDPIECE).
+Not all brackets have midpieces.")
+
+(defun math--big-bracket (bracket-char height baseline)
+  "Composition for BRACKET-CHAR of HEIGHT with BASELINE."
+  (if (<= height 1)
+      (char-to-string bracket-char)
+    (let ((pieces (cdr (assq bracket-char math--big-bracket-alist))))
+      (if (memq nil (mapcar #'char-displayable-p pieces))
+          (char-to-string bracket-char)
+        (let* ((upper (nth 0 pieces))
+               (lower (nth 1 pieces))
+               (extension (nth 2 pieces))
+               (midpiece (nth 3 pieces)))
+          (cons 'vleft        ; alignment doesn't matter; width is 1 char
+                (cons baseline
+                      (mapcar
+                       #'char-to-string
+                       (append
+                        (list upper)
+                        (if midpiece
+                            (let ((lower-ext (/ (- height 3) 2)))
+                              (append
+                               (make-list (- height 3 lower-ext) extension)
+                               (list midpiece)
+                               (make-list lower-ext extension)))
+                          (make-list (- height 2) extension))
+                        (list lower))))))))))
+
+(defun math--comp-bracket (left-bracket right-bracket comp)
+  "Put the composition COMP inside LEFT-BRACKET and RIGHT-BRACKET."
+  (if (eq calc-language 'big)
+      (let ((height (math-comp-height comp))
+            (baseline (1- (math-comp-ascent comp))))
+        (list 'horiz
+              (math--big-bracket left-bracket height baseline)
+              comp
+              (math--big-bracket right-bracket height baseline)))
+    (list 'horiz
+          (char-to-string left-bracket)
+          comp
+          (char-to-string right-bracket))))
+
+(defun math--comp-round-bracket (comp)
+  "Put the composition COMP inside plain brackets."
+  (math--comp-bracket ?\( ?\) comp))
+
 (put 'calcFunc-log 'math-compose-big #'math-compose-log)
 (defun math-compose-log (a _prec)
   (and (= (length a) 3)
@@ -973,18 +1037,14 @@ math-compose-log
 	     (list 'subscr "log"
 		   (let ((calc-language 'flat))
 		     (math-compose-expr (nth 2 a) 1000)))
-	     "("
-	     (math-compose-expr (nth 1 a) 1000)
-	     ")")))
+             (math--comp-round-bracket (math-compose-expr (nth 1 a) 1000)))))
 
 (put 'calcFunc-log10 'math-compose-big #'math-compose-log10)
 (defun math-compose-log10 (a _prec)
   (and (= (length a) 2)
        (list 'horiz
-	     (list 'subscr "log" "10")
-	     "("
-	     (math-compose-expr (nth 1 a) 1000)
-	     ")")))
+             (list 'subscr "log" "10")
+             (math--comp-round-bracket (math-compose-expr (nth 1 a) 1000)))))
 
 (put 'calcFunc-deriv 'math-compose-big #'math-compose-deriv)
 (put 'calcFunc-tderiv 'math-compose-big #'math-compose-deriv)
@@ -1027,12 +1087,9 @@ math-compose-sqrt
 (defun math-compose-choose (a _prec)
   (let ((a1 (math-compose-expr (nth 1 a) 0))
 	(a2 (math-compose-expr (nth 2 a) 0)))
-    (list 'horiz
-	  "("
-	  (list 'vcent
-		(math-comp-height a1)
-		a1 " " a2)
-	  ")")))
+    (math--comp-round-bracket (list 'vcent
+		                    (+ (math-comp-height a1))
+		                    a1 " " a2))))
 
 (put 'calcFunc-integ 'math-compose-big #'math-compose-integ)
 (defun math-compose-integ (a prec)
@@ -1052,9 +1109,12 @@ math-compose-integ
 						       "d%s"
 						       (nth 1 (nth 2 a)))))
 					 (nth 1 a)) 185))
-	      (calc-language 'flat)
-	      (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
-	      (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0)))
+	      (low (and (nth 3 a)
+	                (let ((calc-language 'flat))
+                          (math-compose-expr (nth 3 a) 0))))
+	      (high (and (nth 4 a)
+	                 (let ((calc-language 'flat))
+                           (math-compose-expr (nth 4 a) 0))))
               ;; Check if we have Unicode integral top/bottom parts.
               (fancy (and (char-displayable-p ?⌠)
                           (char-displayable-p ?⌡)))
@@ -1066,40 +1126,47 @@ math-compose-integ
                                 ((char-displayable-p ?│) "│ ")
                                 ;; U+007C VERTICAL LINE
                                 (t "| "))))
-	 (list 'horiz
-	       (if parens "(" "")
-	       (append (list 'vcent (if fancy
-                                        (if high 2 1)
-                                      (if high 3 2)))
-		       (and high (list (if fancy
-                                           (list 'horiz high " ")
-                                         (list 'horiz "  " high))))
-                       (if fancy
-                           (list "⌠ " fancy-stem "⌡ ")
-		         '("  /"
-			   " | "
-			   " | "
-			   " | "
-			   "/  "))
-		       (and low (list (if fancy
-                                          (list 'horiz low " ")
-                                        (list 'horiz low "  ")))))
-	       expr
-	       (if over
-		   ""
-		 (list 'horiz " d" var))
-	       (if parens ")" "")))))
+         (let ((comp
+	        (list 'horiz
+	              (append (list 'vcent (if fancy
+                                               (if high 2 1)
+                                             (if high 3 2)))
+		              (and high (list (if fancy
+                                                  (list 'horiz high " ")
+                                                (list 'horiz "  " high))))
+                              (if fancy
+                                  (list "⌠ " fancy-stem "⌡ ")
+		                '("  /"
+			          " | "
+			          " | "
+			          " | "
+			          "/  "))
+		              (and low (list (if fancy
+                                                 (list 'horiz low " ")
+                                               (list 'horiz low "  ")))))
+	              expr
+	              (if over
+		          ""
+		        (list 'horiz " d" var)))))
+           (if parens
+               (math--comp-round-bracket comp)
+             comp)))))
 
 (put 'calcFunc-sum 'math-compose-big #'math-compose-sum)
 (defun math-compose-sum (a prec)
   (and (memq (length a) '(3 5 6))
        (let* ((expr (math-compose-expr (nth 1 a) 185))
-	      (calc-language 'flat)
-	      (var (math-compose-expr (nth 2 a) 0))
-	      (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
-	      (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0))))
-	 (list 'horiz
-	       (if (memq prec '(180 201)) "(" "")
+	      (var
+	       (let ((calc-language 'flat))
+                 (math-compose-expr (nth 2 a) 0)))
+	      (low (and (nth 3 a)
+	                (let ((calc-language 'flat))
+                          (math-compose-expr (nth 3 a) 0))))
+	      (high (and (nth 4 a)
+	                 (let ((calc-language 'flat))
+                           (math-compose-vector (nthcdr 4 a) ", " 0))))
+              (comp
+	       (list 'horiz
 	       (append (list 'vcent (if high 3 2))
 		       (and high (list high))
 		       '("---- "
@@ -1112,32 +1179,42 @@ math-compose-sum
 			 (list var)))
 	       (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
 		   " " "")
-	       expr
-	       (if (memq prec '(180 201)) ")" "")))))
+	       expr)))
+	 (if (memq prec '(180 201))
+             (math--comp-round-bracket comp)
+           comp))))
 
 (put 'calcFunc-prod 'math-compose-big #'math-compose-prod)
 (defun math-compose-prod (a prec)
   (and (memq (length a) '(3 5 6))
        (let* ((expr (math-compose-expr (nth 1 a) 198))
-	      (calc-language 'flat)
-	      (var (math-compose-expr (nth 2 a) 0))
-	      (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
-	      (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0))))
-	 (list 'horiz
-	       (if (memq prec '(196 201)) "(" "")
-	       (append (list 'vcent (if high 3 2))
-		       (and high (list high))
-		       '("----- "
-			 " | |  "
-			 " | |  "
-			 " | |  ")
-		       (if low
-			   (list (list 'horiz var " = " low))
-			 (list var)))
-	       (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
-		   " " "")
-	       expr
-	       (if (memq prec '(196 201)) ")" "")))))
+	      (var
+               (let ((calc-language 'flat))
+                 (math-compose-expr (nth 2 a) 0)))
+	      (low (and (nth 3 a)
+                        (let ((calc-language 'flat))
+                          (math-compose-expr (nth 3 a) 0))))
+	      (high (and (nth 4 a)
+                         (let ((calc-language 'flat))
+                           (math-compose-vector (nthcdr 4 a) ", " 0))))
+              (comp
+	       (list 'horiz
+	             (append (list 'vcent (if high 3 2))
+		             (and high (list high))
+		             '("----- "
+			       " | |  "
+			       " | |  "
+			       " | |  ")
+		             (if low
+			         (list (list 'horiz var " = " low))
+			       (list var)))
+	             (if (memq (car-safe (nth 1 a))
+                               '(calcFunc-sum calcFunc-prod))
+		         " " "")
+	             expr)))
+         (if (memq prec '(196 201))
+             (math--comp-round-bracket comp)
+           comp))))
 
 ;; The variables math-svo-c, math-svo-wid and math-svo-off are local
 ;; to math-stack-value-offset in calc.el, but are used by
-- 
2.21.1 (Apple Git-122.3)


[-- Attachment #3: Type: text/plain, Size: 2 bytes --]




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* bug#45917: [PATCH] Use big brackets in Calc in big mode
  2021-01-16 17:10 bug#45917: [PATCH] Use big brackets in Calc in big mode Mattias Engdegård
@ 2021-01-19  5:37 ` Lars Ingebrigtsen
  2021-01-19 10:12   ` Mattias Engdegård
  0 siblings, 1 reply; 5+ messages in thread
From: Lars Ingebrigtsen @ 2021-01-19  5:37 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: 45917

Mattias Engdegård <mattiase@acm.org> writes:

> The attached patch makes Calc use big brackets in Big mode when the
> Unicode characters are available. This makes for prettier display
> which is sort of the point of using Big mode. It follows previous use
> of Unicode characters for square root and integral signs.

Makes sense to me, but...

> As far as I can tell the only reasons for not applying this would be
> that it is common with fonts or terminals where this doesn't look
> good,

... would it be possible to have a fallback if the display doesn't
support these characters?

> or that the resulting formula isn't recognised by the
> embedded-mode parser (which is already the case with several other
> constructs).

Yeah.  Or there could be a variable to allow the user to not use these
fancy brackets if this is important for them?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#45917: [PATCH] Use big brackets in Calc in big mode
  2021-01-19  5:37 ` Lars Ingebrigtsen
@ 2021-01-19 10:12   ` Mattias Engdegård
  2021-01-19 15:45     ` Lars Ingebrigtsen
  0 siblings, 1 reply; 5+ messages in thread
From: Mattias Engdegård @ 2021-01-19 10:12 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 45917

19 jan. 2021 kl. 06.37 skrev Lars Ingebrigtsen <larsi@gnus.org>:

> ... would it be possible to have a fallback if the display doesn't
> support these characters?

Yes, all Unicode characters are checked using char-displayable-p in the patch. However, some characters may be technically displayable but not very pretty, or have awkward metrics.

That said, the brackets look fine where I've tested them so it's probably not a serious concern.

> Yeah.  Or there could be a variable to allow the user to not use these
> fancy brackets if this is important for them?

Maybe, but Calc already has rather too many variables and should we have separate variables for all non-ASCII features then, like the square root sign?

We are just speculating here. I'd hoped for concrete cheerful evidence like 'looks terrible on my terminal', 'completely destroys embedded-mode for me'...






^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#45917: [PATCH] Use big brackets in Calc in big mode
  2021-01-19 10:12   ` Mattias Engdegård
@ 2021-01-19 15:45     ` Lars Ingebrigtsen
  2021-01-19 17:59       ` Mattias Engdegård
  0 siblings, 1 reply; 5+ messages in thread
From: Lars Ingebrigtsen @ 2021-01-19 15:45 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: 45917

Mattias Engdegård <mattiase@acm.org> writes:

> 19 jan. 2021 kl. 06.37 skrev Lars Ingebrigtsen <larsi@gnus.org>:
>
>> ... would it be possible to have a fallback if the display doesn't
>> support these characters?
>
> Yes, all Unicode characters are checked using char-displayable-p in
> the patch.

Duh.  I skimmed the patch, but I missed that bit...

> However, some characters may be technically displayable but
> not very pretty, or have awkward metrics.
>
> That said, the brackets look fine where I've tested them so it's
> probably not a serious concern.

Yup.

>> Yeah.  Or there could be a variable to allow the user to not use these
>> fancy brackets if this is important for them?
>
> Maybe, but Calc already has rather too many variables and should we
> have separate variables for all non-ASCII features then, like the
> square root sign?

Possibly?  But I see you've just pushed a fix for parsing the root
sign.  :-)

> We are just speculating here. I'd hoped for concrete cheerful evidence
> like 'looks terrible on my terminal', 'completely destroys
> embedded-mode for me'...

I'm guessing you won't get feedback like that until you push this
change.  :-)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#45917: [PATCH] Use big brackets in Calc in big mode
  2021-01-19 15:45     ` Lars Ingebrigtsen
@ 2021-01-19 17:59       ` Mattias Engdegård
  0 siblings, 0 replies; 5+ messages in thread
From: Mattias Engdegård @ 2021-01-19 17:59 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 45917-done

19 jan. 2021 kl. 16.45 skrev Lars Ingebrigtsen <larsi@gnus.org>:

>> Maybe, but Calc already has rather too many variables and should we
>> have separate variables for all non-ASCII features then, like the
>> square root sign?
> 
> Possibly?  But I see you've just pushed a fix for parsing the root
> sign.  :-)

Yes, it turned out to be easy! Parsing big brackets is probably not quite as easy; I'm not even going to try.

>> We are just speculating here. I'd hoped for concrete cheerful evidence
>> like 'looks terrible on my terminal', 'completely destroys
>> embedded-mode for me'...
> 
> I'm guessing you won't get feedback like that until you push this
> change.  :-)

Right, now done. Let's see if anything turns up.






^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-01-19 17:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-16 17:10 bug#45917: [PATCH] Use big brackets in Calc in big mode Mattias Engdegård
2021-01-19  5:37 ` Lars Ingebrigtsen
2021-01-19 10:12   ` Mattias Engdegård
2021-01-19 15:45     ` Lars Ingebrigtsen
2021-01-19 17:59       ` Mattias Engdegård

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).