aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Engdegård2021-01-16 17:30:57 +0100
committerMattias Engdegård2021-01-19 19:00:09 +0100
commitbfa140d7cf82ed640d033391cde505ab020de0f2 (patch)
treedbc7b21b13ce2d82034648ed9efe463d8fea19cf
parent039ab602cbf877eef1b18c6ef8b36dcf52ece5c4 (diff)
downloademacs-bfa140d7cf82ed640d033391cde505ab020de0f2.tar.gz
emacs-bfa140d7cf82ed640d033391cde505ab020de0f2.zip
Calc: use Unicode brackets in Big mode when available (bug#45917)
* 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.
-rw-r--r--lisp/calc/calccomp.el247
1 files changed, 162 insertions, 85 deletions
diff --git a/lisp/calc/calccomp.el b/lisp/calc/calccomp.el
index 07e70cad0a8..5f38ee71c78 100644
--- a/lisp/calc/calccomp.el
+++ b/lisp/calc/calccomp.el
@@ -138,19 +138,19 @@
138 (math-format-number (nth 2 aa)))))) 138 (math-format-number (nth 2 aa))))))
139 (if (= calc-number-radix 10) 139 (if (= calc-number-radix 10)
140 c 140 c
141 (list 'horiz "(" c 141 (list 'subscr (math--comp-round-bracket c)
142 (list 'subscr ")" 142 (int-to-string calc-number-radix))))
143 (int-to-string calc-number-radix)))))
144 (math-format-number a))) 143 (math-format-number a)))
145 (if (not (eq calc-language 'big)) 144 (if (not (eq calc-language 'big))
146 (math-format-number a prec) 145 (math-format-number a prec)
147 (if (memq (car-safe a) '(cplx polar)) 146 (if (memq (car-safe a) '(cplx polar))
148 (if (math-zerop (nth 2 a)) 147 (if (math-zerop (nth 2 a))
149 (math-compose-expr (nth 1 a) prec) 148 (math-compose-expr (nth 1 a) prec)
150 (list 'horiz "(" 149 (math--comp-round-bracket
151 (math-compose-expr (nth 1 a) 0) 150 (list 'horiz
152 (if (eq (car a) 'cplx) ", " "; ") 151 (math-compose-expr (nth 1 a) 0)
153 (math-compose-expr (nth 2 a) 0) ")")) 152 (if (eq (car a) 'cplx) ", " "; ")
153 (math-compose-expr (nth 2 a) 0))))
154 (if (or (= calc-number-radix 10) 154 (if (or (= calc-number-radix 10)
155 (not (Math-realp a)) 155 (not (Math-realp a))
156 (and calc-group-digits 156 (and calc-group-digits
@@ -340,12 +340,13 @@
340 (funcall spfn a prec) 340 (funcall spfn a prec)
341 (math-compose-var a))))) 341 (math-compose-var a)))))
342 ((eq (car a) 'intv) 342 ((eq (car a) 'intv)
343 (list 'horiz 343 (math--comp-bracket
344 (if (memq (nth 1 a) '(0 1)) "(" "[") 344 (if (memq (nth 1 a) '(0 1)) ?\( ?\[)
345 (math-compose-expr (nth 2 a) 0) 345 (if (memq (nth 1 a) '(0 2)) ?\) ?\])
346 " .. " 346 (list 'horiz
347 (math-compose-expr (nth 3 a) 0) 347 (math-compose-expr (nth 2 a) 0)
348 (if (memq (nth 1 a) '(0 2)) ")" "]"))) 348 " .. "
349 (math-compose-expr (nth 3 a) 0))))
349 ((eq (car a) 'date) 350 ((eq (car a) 'date)
350 (if (eq (car calc-date-format) 'X) 351 (if (eq (car calc-date-format) 'X)
351 (math-format-date a) 352 (math-format-date a)
@@ -377,7 +378,7 @@
377 (and (eq (car-safe (nth 1 a)) 'cplx) 378 (and (eq (car-safe (nth 1 a)) 'cplx)
378 (math-negp (nth 1 (nth 1 a))) 379 (math-negp (nth 1 (nth 1 a)))
379 (eq (nth 2 (nth 1 a)) 0))) 380 (eq (nth 2 (nth 1 a)) 0)))
380 (list 'horiz "(" (math-compose-expr (nth 1 a) 0) ")") 381 (math--comp-round-bracket (math-compose-expr (nth 1 a) 0))
381 (math-compose-expr (nth 1 a) 201)) 382 (math-compose-expr (nth 1 a) 201))
382 (let ((calc-language 'flat) 383 (let ((calc-language 'flat)
383 (calc-number-radix 10) 384 (calc-number-radix 10)
@@ -444,7 +445,7 @@
444 (if (> prec (nth 2 a)) 445 (if (> prec (nth 2 a))
445 (if (setq spfn (get calc-language 'math-big-parens)) 446 (if (setq spfn (get calc-language 'math-big-parens))
446 (list 'horiz (car spfn) c (cdr spfn)) 447 (list 'horiz (car spfn) c (cdr spfn))
447 (list 'horiz "(" c ")")) 448 (math--comp-round-bracket c))
448 c))) 449 c)))
449 ((and (eq (car a) 'calcFunc-choriz) 450 ((and (eq (car a) 'calcFunc-choriz)
450 (not (eq calc-language 'unform)) 451 (not (eq calc-language 'unform))
@@ -612,7 +613,7 @@
612 (list 'horiz "{left ( " 613 (list 'horiz "{left ( "
613 (math-compose-expr a -1) 614 (math-compose-expr a -1)
614 " right )}"))) 615 " right )}")))
615 (list 'horiz "(" (math-compose-expr a 0) ")")))) 616 (math--comp-round-bracket (math-compose-expr a 0)))))
616 ((and (memq calc-language '(tex latex)) 617 ((and (memq calc-language '(tex latex))
617 (memq (car a) '(/ calcFunc-choose calcFunc-evalto)) 618 (memq (car a) '(/ calcFunc-choose calcFunc-evalto))
618 (>= prec 0)) 619 (>= prec 0))
@@ -638,7 +639,7 @@
638 (rhs (math-compose-expr (nth 2 a) (nth 3 op) (eq (nth 1 op) '/)))) 639 (rhs (math-compose-expr (nth 2 a) (nth 3 op) (eq (nth 1 op) '/))))
639 (and (equal (car op) "^") 640 (and (equal (car op) "^")
640 (eq (math-comp-first-char lhs) ?-) 641 (eq (math-comp-first-char lhs) ?-)
641 (setq lhs (list 'horiz "(" lhs ")"))) 642 (setq lhs (math--comp-round-bracket lhs)))
642 (and (memq calc-language '(tex latex)) 643 (and (memq calc-language '(tex latex))
643 (or (equal (car op) "^") (equal (car op) "_")) 644 (or (equal (car op) "^") (equal (car op) "_"))
644 (not (and (stringp rhs) (= (length rhs) 1))) 645 (not (and (stringp rhs) (= (length rhs) 1)))
@@ -721,7 +722,7 @@
721 (list 'horiz "{left ( " 722 (list 'horiz "{left ( "
722 (math-compose-expr a -1) 723 (math-compose-expr a -1)
723 " right )}"))) 724 " right )}")))
724 (list 'horiz "(" (math-compose-expr a 0) ")")))) 725 (math--comp-round-bracket (math-compose-expr a 0)))))
725 (t 726 (t
726 (let ((lhs (math-compose-expr (nth 1 a) (nth 2 op)))) 727 (let ((lhs (math-compose-expr (nth 1 a) (nth 2 op))))
727 (list 'horiz 728 (list 'horiz
@@ -759,7 +760,7 @@
759 (list 'horiz "{left ( " 760 (list 'horiz "{left ( "
760 (math-compose-expr a -1) 761 (math-compose-expr a -1)
761 " right )}"))) 762 " right )}")))
762 (list 'horiz "(" (math-compose-expr a 0) ")")))) 763 (math--comp-round-bracket (math-compose-expr a 0)))))
763 (t 764 (t
764 (let ((rhs (math-compose-expr (nth 1 a) (nth 3 op)))) 765 (let ((rhs (math-compose-expr (nth 1 a) (nth 3 op))))
765 (list 'horiz 766 (list 'horiz
@@ -966,6 +967,69 @@
966 (and (memq (car a) '(^ calcFunc-subscr)) 967 (and (memq (car a) '(^ calcFunc-subscr))
967 (math-tex-expr-is-flat (nth 1 a))))) 968 (math-tex-expr-is-flat (nth 1 a)))))
968 969
970;; FIXME: maybe try box drawing chars if big bracket chars are unavailable,
971;; like ┌ ┐n
972;; │a + b│ ┌ a + b ┐n
973;; │-----│ or │ ----- │ ?
974;; │ c │ └ c ┘
975;; └ ┘
976;; They are more common than the chars below, but look a bit square.
977;; Rounded corners exist but are less commonly available.
978
979(defconst math--big-bracket-alist
980 '((?\( . (?⎛ ?⎝ ?⎜))
981 (?\) . (?⎞ ?⎠ ?⎟))
982 (?\[ . (?⎡ ?⎣ ?⎢))
983 (?\] . (?⎤ ?⎦ ?⎥))
984 (?\{ . (?⎧ ?⎩ ?⎪ ?⎨))
985 (?\} . (?⎫ ?⎭ ?⎪ ?⎬)))
986 "Alist mapping bracket chars to (UPPER LOWER EXTENSION MIDPIECE).
987Not all brackets have midpieces.")
988
989(defun math--big-bracket (bracket-char height baseline)
990 "Composition for BRACKET-CHAR of HEIGHT with BASELINE."
991 (if (<= height 1)
992 (char-to-string bracket-char)
993 (let ((pieces (cdr (assq bracket-char math--big-bracket-alist))))
994 (if (memq nil (mapcar #'char-displayable-p pieces))
995 (char-to-string bracket-char)
996 (let* ((upper (nth 0 pieces))
997 (lower (nth 1 pieces))
998 (extension (nth 2 pieces))
999 (midpiece (nth 3 pieces)))
1000 (cons 'vleft ; alignment doesn't matter; width is 1 char
1001 (cons baseline
1002 (mapcar
1003 #'char-to-string
1004 (append
1005 (list upper)
1006 (if midpiece
1007 (let ((lower-ext (/ (- height 3) 2)))
1008 (append
1009 (make-list (- height 3 lower-ext) extension)
1010 (list midpiece)
1011 (make-list lower-ext extension)))
1012 (make-list (- height 2) extension))
1013 (list lower))))))))))
1014
1015(defun math--comp-bracket (left-bracket right-bracket comp)
1016 "Put the composition COMP inside LEFT-BRACKET and RIGHT-BRACKET."
1017 (if (eq calc-language 'big)
1018 (let ((height (math-comp-height comp))
1019 (baseline (1- (math-comp-ascent comp))))
1020 (list 'horiz
1021 (math--big-bracket left-bracket height baseline)
1022 comp
1023 (math--big-bracket right-bracket height baseline)))
1024 (list 'horiz
1025 (char-to-string left-bracket)
1026 comp
1027 (char-to-string right-bracket))))
1028
1029(defun math--comp-round-bracket (comp)
1030 "Put the composition COMP inside plain brackets."
1031 (math--comp-bracket ?\( ?\) comp))
1032
969(put 'calcFunc-log 'math-compose-big #'math-compose-log) 1033(put 'calcFunc-log 'math-compose-big #'math-compose-log)
970(defun math-compose-log (a _prec) 1034(defun math-compose-log (a _prec)
971 (and (= (length a) 3) 1035 (and (= (length a) 3)
@@ -973,18 +1037,14 @@
973 (list 'subscr "log" 1037 (list 'subscr "log"
974 (let ((calc-language 'flat)) 1038 (let ((calc-language 'flat))
975 (math-compose-expr (nth 2 a) 1000))) 1039 (math-compose-expr (nth 2 a) 1000)))
976 "(" 1040 (math--comp-round-bracket (math-compose-expr (nth 1 a) 1000)))))
977 (math-compose-expr (nth 1 a) 1000)
978 ")")))
979 1041
980(put 'calcFunc-log10 'math-compose-big #'math-compose-log10) 1042(put 'calcFunc-log10 'math-compose-big #'math-compose-log10)
981(defun math-compose-log10 (a _prec) 1043(defun math-compose-log10 (a _prec)
982 (and (= (length a) 2) 1044 (and (= (length a) 2)
983 (list 'horiz 1045 (list 'horiz
984 (list 'subscr "log" "10") 1046 (list 'subscr "log" "10")
985 "(" 1047 (math--comp-round-bracket (math-compose-expr (nth 1 a) 1000)))))
986 (math-compose-expr (nth 1 a) 1000)
987 ")")))
988 1048
989(put 'calcFunc-deriv 'math-compose-big #'math-compose-deriv) 1049(put 'calcFunc-deriv 'math-compose-big #'math-compose-deriv)
990(put 'calcFunc-tderiv 'math-compose-big #'math-compose-deriv) 1050(put 'calcFunc-tderiv 'math-compose-big #'math-compose-deriv)
@@ -1027,12 +1087,9 @@
1027(defun math-compose-choose (a _prec) 1087(defun math-compose-choose (a _prec)
1028 (let ((a1 (math-compose-expr (nth 1 a) 0)) 1088 (let ((a1 (math-compose-expr (nth 1 a) 0))
1029 (a2 (math-compose-expr (nth 2 a) 0))) 1089 (a2 (math-compose-expr (nth 2 a) 0)))
1030 (list 'horiz 1090 (math--comp-round-bracket (list 'vcent
1031 "(" 1091 (+ (math-comp-height a1))
1032 (list 'vcent 1092 a1 " " a2))))
1033 (math-comp-height a1)
1034 a1 " " a2)
1035 ")")))
1036 1093
1037(put 'calcFunc-integ 'math-compose-big #'math-compose-integ) 1094(put 'calcFunc-integ 'math-compose-big #'math-compose-integ)
1038(defun math-compose-integ (a prec) 1095(defun math-compose-integ (a prec)
@@ -1052,9 +1109,12 @@
1052 "d%s" 1109 "d%s"
1053 (nth 1 (nth 2 a))))) 1110 (nth 1 (nth 2 a)))))
1054 (nth 1 a)) 185)) 1111 (nth 1 a)) 185))
1055 (calc-language 'flat) 1112 (low (and (nth 3 a)
1056 (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0))) 1113 (let ((calc-language 'flat))
1057 (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0))) 1114 (math-compose-expr (nth 3 a) 0))))
1115 (high (and (nth 4 a)
1116 (let ((calc-language 'flat))
1117 (math-compose-expr (nth 4 a) 0))))
1058 ;; Check if we have Unicode integral top/bottom parts. 1118 ;; Check if we have Unicode integral top/bottom parts.
1059 (fancy (and (char-displayable-p ?⌠) 1119 (fancy (and (char-displayable-p ?⌠)
1060 (char-displayable-p ?⌡))) 1120 (char-displayable-p ?⌡)))
@@ -1066,40 +1126,47 @@
1066 ((char-displayable-p ?│) "│ ") 1126 ((char-displayable-p ?│) "│ ")
1067 ;; U+007C VERTICAL LINE 1127 ;; U+007C VERTICAL LINE
1068 (t "| ")))) 1128 (t "| "))))
1069 (list 'horiz 1129 (let ((comp
1070 (if parens "(" "") 1130 (list 'horiz
1071 (append (list 'vcent (if fancy 1131 (append (list 'vcent (if fancy
1072 (if high 2 1) 1132 (if high 2 1)
1073 (if high 3 2))) 1133 (if high 3 2)))
1074 (and high (list (if fancy 1134 (and high (list (if fancy
1075 (list 'horiz high " ") 1135 (list 'horiz high " ")
1076 (list 'horiz " " high)))) 1136 (list 'horiz " " high))))
1077 (if fancy 1137 (if fancy
1078 (list "⌠ " fancy-stem "⌡ ") 1138 (list "⌠ " fancy-stem "⌡ ")
1079 '(" /" 1139 '(" /"
1080 " | " 1140 " | "
1081 " | " 1141 " | "
1082 " | " 1142 " | "
1083 "/ ")) 1143 "/ "))
1084 (and low (list (if fancy 1144 (and low (list (if fancy
1085 (list 'horiz low " ") 1145 (list 'horiz low " ")
1086 (list 'horiz low " "))))) 1146 (list 'horiz low " ")))))
1087 expr 1147 expr
1088 (if over 1148 (if over
1089 "" 1149 ""
1090 (list 'horiz " d" var)) 1150 (list 'horiz " d" var)))))
1091 (if parens ")" ""))))) 1151 (if parens
1152 (math--comp-round-bracket comp)
1153 comp)))))
1092 1154
1093(put 'calcFunc-sum 'math-compose-big #'math-compose-sum) 1155(put 'calcFunc-sum 'math-compose-big #'math-compose-sum)
1094(defun math-compose-sum (a prec) 1156(defun math-compose-sum (a prec)
1095 (and (memq (length a) '(3 5 6)) 1157 (and (memq (length a) '(3 5 6))
1096 (let* ((expr (math-compose-expr (nth 1 a) 185)) 1158 (let* ((expr (math-compose-expr (nth 1 a) 185))
1097 (calc-language 'flat) 1159 (var
1098 (var (math-compose-expr (nth 2 a) 0)) 1160 (let ((calc-language 'flat))
1099 (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0))) 1161 (math-compose-expr (nth 2 a) 0)))
1100 (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0)))) 1162 (low (and (nth 3 a)
1101 (list 'horiz 1163 (let ((calc-language 'flat))
1102 (if (memq prec '(180 201)) "(" "") 1164 (math-compose-expr (nth 3 a) 0))))
1165 (high (and (nth 4 a)
1166 (let ((calc-language 'flat))
1167 (math-compose-vector (nthcdr 4 a) ", " 0))))
1168 (comp
1169 (list 'horiz
1103 (append (list 'vcent (if high 3 2)) 1170 (append (list 'vcent (if high 3 2))
1104 (and high (list high)) 1171 (and high (list high))
1105 '("---- " 1172 '("---- "
@@ -1112,32 +1179,42 @@
1112 (list var))) 1179 (list var)))
1113 (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod)) 1180 (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
1114 " " "") 1181 " " "")
1115 expr 1182 expr)))
1116 (if (memq prec '(180 201)) ")" ""))))) 1183 (if (memq prec '(180 201))
1184 (math--comp-round-bracket comp)
1185 comp))))
1117 1186
1118(put 'calcFunc-prod 'math-compose-big #'math-compose-prod) 1187(put 'calcFunc-prod 'math-compose-big #'math-compose-prod)
1119(defun math-compose-prod (a prec) 1188(defun math-compose-prod (a prec)
1120 (and (memq (length a) '(3 5 6)) 1189 (and (memq (length a) '(3 5 6))
1121 (let* ((expr (math-compose-expr (nth 1 a) 198)) 1190 (let* ((expr (math-compose-expr (nth 1 a) 198))
1122 (calc-language 'flat) 1191 (var
1123 (var (math-compose-expr (nth 2 a) 0)) 1192 (let ((calc-language 'flat))
1124 (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0))) 1193 (math-compose-expr (nth 2 a) 0)))
1125 (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0)))) 1194 (low (and (nth 3 a)
1126 (list 'horiz 1195 (let ((calc-language 'flat))
1127 (if (memq prec '(196 201)) "(" "") 1196 (math-compose-expr (nth 3 a) 0))))
1128 (append (list 'vcent (if high 3 2)) 1197 (high (and (nth 4 a)
1129 (and high (list high)) 1198 (let ((calc-language 'flat))
1130 '("----- " 1199 (math-compose-vector (nthcdr 4 a) ", " 0))))
1131 " | | " 1200 (comp
1132 " | | " 1201 (list 'horiz
1133 " | | ") 1202 (append (list 'vcent (if high 3 2))
1134 (if low 1203 (and high (list high))
1135 (list (list 'horiz var " = " low)) 1204 '("----- "
1136 (list var))) 1205 " | | "
1137 (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod)) 1206 " | | "
1138 " " "") 1207 " | | ")
1139 expr 1208 (if low
1140 (if (memq prec '(196 201)) ")" ""))))) 1209 (list (list 'horiz var " = " low))
1210 (list var)))
1211 (if (memq (car-safe (nth 1 a))
1212 '(calcFunc-sum calcFunc-prod))
1213 " " "")
1214 expr)))
1215 (if (memq prec '(196 201))
1216 (math--comp-round-bracket comp)
1217 comp))))
1141 1218
1142;; The variables math-svo-c, math-svo-wid and math-svo-off are local 1219;; The variables math-svo-c, math-svo-wid and math-svo-off are local
1143;; to math-stack-value-offset in calc.el, but are used by 1220;; to math-stack-value-offset in calc.el, but are used by