summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/cl-extra.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/cl-extra.el')
-rw-r--r--lisp/emacs-lisp/cl-extra.el119
1 files changed, 85 insertions, 34 deletions
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index 749061b7bc5..021ef232749 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -89,7 +89,7 @@ strings case-insensitively."
;;; Control structures.
;;;###autoload
-(defun cl--mapcar-many (cl-func cl-seqs)
+(defun cl--mapcar-many (cl-func cl-seqs &optional acc)
(if (cdr (cdr cl-seqs))
(let* ((cl-res nil)
(cl-n (apply 'min (mapcar 'length cl-seqs)))
@@ -106,20 +106,23 @@ strings case-insensitively."
(setcar cl-p1 (cdr (car cl-p1))))
(aref (car cl-p1) cl-i)))
(setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))
- (push (apply cl-func cl-args) cl-res)
+ (if acc
+ (push (apply cl-func cl-args) cl-res)
+ (apply cl-func cl-args))
(setq cl-i (1+ cl-i)))
- (nreverse cl-res))
+ (and acc (nreverse cl-res)))
(let ((cl-res nil)
(cl-x (car cl-seqs))
(cl-y (nth 1 cl-seqs)))
(let ((cl-n (min (length cl-x) (length cl-y)))
(cl-i -1))
(while (< (setq cl-i (1+ cl-i)) cl-n)
- (push (funcall cl-func
- (if (consp cl-x) (pop cl-x) (aref cl-x cl-i))
- (if (consp cl-y) (pop cl-y) (aref cl-y cl-i)))
- cl-res)))
- (nreverse cl-res))))
+ (let ((val (funcall cl-func
+ (if (consp cl-x) (pop cl-x) (aref cl-x cl-i))
+ (if (consp cl-y) (pop cl-y) (aref cl-y cl-i)))))
+ (when acc
+ (push val cl-res)))))
+ (and acc (nreverse cl-res)))))
;;;###autoload
(defun cl-map (cl-type cl-func cl-seq &rest cl-rest)
@@ -142,7 +145,7 @@ the elements themselves.
(while (not (memq nil cl-args))
(push (apply cl-func cl-args) cl-res)
(setq cl-p cl-args)
- (while cl-p (setcar cl-p (cdr (pop cl-p)) )))
+ (while cl-p (setcar cl-p (cdr (pop cl-p)))))
(nreverse cl-res))
(let ((cl-res nil))
(while cl-list
@@ -155,8 +158,14 @@ the elements themselves.
"Like `cl-mapcar', but does not accumulate values returned by the function.
\n(fn FUNCTION SEQUENCE...)"
(if cl-rest
- (progn (apply 'cl-map nil cl-func cl-seq cl-rest)
- cl-seq)
+ (if (or (cdr cl-rest) (nlistp cl-seq) (nlistp (car cl-rest)))
+ (progn
+ (cl--mapcar-many cl-func (cons cl-seq cl-rest))
+ cl-seq)
+ (let ((cl-x cl-seq) (cl-y (car cl-rest)))
+ (while (and cl-x cl-y)
+ (funcall cl-func (pop cl-x) (pop cl-y)))
+ cl-seq))
(mapc cl-func cl-seq)))
;;;###autoload
@@ -164,7 +173,12 @@ the elements themselves.
"Like `cl-maplist', but does not accumulate values returned by the function.
\n(fn FUNCTION LIST...)"
(if cl-rest
- (apply 'cl-maplist cl-func cl-list cl-rest)
+ (let ((cl-args (cons cl-list (copy-sequence cl-rest)))
+ cl-p)
+ (while (not (memq nil cl-args))
+ (apply cl-func cl-args)
+ (setq cl-p cl-args)
+ (while cl-p (setcar cl-p (cdr (pop cl-p))))))
(let ((cl-p cl-list))
(while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p)))))
cl-list)
@@ -173,7 +187,9 @@ the elements themselves.
(defun cl-mapcan (cl-func cl-seq &rest cl-rest)
"Like `cl-mapcar', but nconc's together the values returned by the function.
\n(fn FUNCTION SEQUENCE...)"
- (apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest)))
+ (if cl-rest
+ (apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest))
+ (mapcan cl-func cl-seq)))
;;;###autoload
(defun cl-mapcon (cl-func cl-list &rest cl-rest)
@@ -591,13 +607,7 @@ too large if positive or too small if negative)."
\n(fn SYMBOL PROPNAME &optional DEFAULT)"
(declare (compiler-macro cl--compiler-macro-get)
(gv-setter (lambda (store) (ignore def) `(put ,sym ,tag ,store))))
- (or (get sym tag)
- (and def
- ;; Make sure `def' is really absent as opposed to set to nil.
- (let ((plist (symbol-plist sym)))
- (while (and plist (not (eq (car plist) tag)))
- (setq plist (cdr (cdr plist))))
- (if plist (car (cdr plist)) def)))))
+ (cl-getf (symbol-plist sym) tag def))
(autoload 'cl--compiler-macro-get "cl-macs")
;;;###autoload
@@ -616,26 +626,20 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
,(funcall setter
`(cl--set-getf ,getter ,k ,val))
,val)))))))))
- (setplist '--cl-getf-symbol-- plist)
- (or (get '--cl-getf-symbol-- tag)
- ;; Originally we called cl-get here,
- ;; but that fails, because cl-get has a compiler macro
- ;; definition that uses getf!
- (when def
- ;; Make sure `def' is really absent as opposed to set to nil.
- (while (and plist (not (eq (car plist) tag)))
- (setq plist (cdr (cdr plist))))
- (if plist (car (cdr plist)) def))))
+ (let ((val-tail (cdr-safe (plist-member plist tag))))
+ (if val-tail (car val-tail) def)))
;;;###autoload
(defun cl--set-getf (plist tag val)
- (let ((p plist))
- (while (and p (not (eq (car p) tag))) (setq p (cdr (cdr p))))
- (if p (progn (setcar (cdr p) val) plist) (cl-list* tag val plist))))
+ (let ((val-tail (cdr-safe (plist-member plist tag))))
+ (if val-tail (progn (setcar val-tail val) plist)
+ (cl-list* tag val plist))))
;;;###autoload
(defun cl--do-remf (plist tag)
(let ((p (cdr plist)))
+ ;; Can't use `plist-member' here because it goes to the cons-cell
+ ;; of TAG and we need the one before.
(while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p))))
(and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t))))
@@ -861,6 +865,38 @@ including `cl-block' and `cl-eval-when'."
"\n")))
"\n"))
+(defun cl--print-table (header rows)
+ ;; FIXME: Isn't this functionality already implemented elsewhere?
+ (let ((cols (apply #'vector (mapcar #'string-width header)))
+ (col-space 2))
+ (dolist (row rows)
+ (dotimes (i (length cols))
+ (let* ((x (pop row))
+ (curwidth (aref cols i))
+ (newwidth (if x (string-width x) 0)))
+ (if (> newwidth curwidth)
+ (setf (aref cols i) newwidth)))))
+ (let ((formats '())
+ (col 0))
+ (dotimes (i (length cols))
+ (push (concat (propertize " "
+ 'display
+ `(space :align-to ,(+ col col-space)))
+ "%s")
+ formats)
+ (cl-incf col (+ col-space (aref cols i))))
+ (let ((format (mapconcat #'identity (nreverse formats) "")))
+ (insert (apply #'format format
+ (mapcar (lambda (str) (propertize str 'face 'italic))
+ header))
+ "\n")
+ (insert (apply #'format format
+ (mapcar (lambda (str) (make-string (string-width str) ?—))
+ header))
+ "\n")
+ (dolist (row rows)
+ (insert (apply #'format format row) "\n"))))))
+
(defun cl--describe-class-slots (class)
"Print help description for the slots in CLASS.
Outputs to the current buffer."
@@ -873,7 +909,22 @@ Outputs to the current buffer."
(cl-struct-unknown-slot nil))))
(insert (propertize "Instance Allocated Slots:\n\n"
'face 'bold))
- (mapc #'cl--describe-class-slot slots)
+ (let* ((has-doc nil)
+ (slots-strings
+ (mapcar
+ (lambda (slot)
+ (list (cl-prin1-to-string (cl--slot-descriptor-name slot))
+ (cl-prin1-to-string (cl--slot-descriptor-type slot))
+ (cl-prin1-to-string (cl--slot-descriptor-initform slot))
+ (let ((doc (alist-get :documentation
+ (cl--slot-descriptor-props slot))))
+ (if (not doc) ""
+ (setq has-doc t)
+ (substitute-command-keys doc)))))
+ slots)))
+ (cl--print-table `("Name" "Type" "Default" . ,(if has-doc '("Doc")))
+ slots-strings))
+ (insert "\n")
(when (> (length cslots) 0)
(insert (propertize "\nClass Allocated Slots:\n\n" 'face 'bold))
(mapc #'cl--describe-class-slot cslots))))