diff options
| author | Joakim Verona | 2015-02-08 21:55:28 +0100 |
|---|---|---|
| committer | Joakim Verona | 2015-02-08 21:55:28 +0100 |
| commit | 5e1d5ef39ca0d2fbff26d659f2ec6ce863b14529 (patch) | |
| tree | 860e0d53399626aee6249ebb5f972879f403b228 /lisp/emacs-lisp | |
| parent | 148262ce3db990ed16989341345e232570b3a338 (diff) | |
| parent | 7d631aa0ffab875e4979727f632703ad5b4100a2 (diff) | |
| download | emacs-xwidget.tar.gz emacs-xwidget.zip | |
merge masterxwidget
Diffstat (limited to 'lisp/emacs-lisp')
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 59 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cconv.el | 31 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-base.el | 3 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-compat.el | 7 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-core.el | 43 | ||||
| -rw-r--r-- | lisp/emacs-lisp/package.el | 60 | ||||
| -rw-r--r-- | lisp/emacs-lisp/seq.el | 55 |
7 files changed, 186 insertions, 72 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 2bd8d07851b..548aaa9626b 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -31,6 +31,10 @@ | |||
| 31 | ;; faster. [`LAP' == `Lisp Assembly Program'.] | 31 | ;; faster. [`LAP' == `Lisp Assembly Program'.] |
| 32 | ;; The user entry points are byte-compile-file and byte-recompile-directory. | 32 | ;; The user entry points are byte-compile-file and byte-recompile-directory. |
| 33 | 33 | ||
| 34 | ;;; Todo: | ||
| 35 | |||
| 36 | ;; - Turn "not bound at runtime" functions into autoloads. | ||
| 37 | |||
| 34 | ;;; Code: | 38 | ;;; Code: |
| 35 | 39 | ||
| 36 | ;; ======================================================================== | 40 | ;; ======================================================================== |
| @@ -450,7 +454,7 @@ Return the compile-time value of FORM." | |||
| 450 | (eval-when-compile . ,(lambda (&rest body) | 454 | (eval-when-compile . ,(lambda (&rest body) |
| 451 | (let ((result nil)) | 455 | (let ((result nil)) |
| 452 | (byte-compile-recurse-toplevel | 456 | (byte-compile-recurse-toplevel |
| 453 | (cons 'progn body) | 457 | (macroexp-progn body) |
| 454 | (lambda (form) | 458 | (lambda (form) |
| 455 | (setf result | 459 | (setf result |
| 456 | (byte-compile-eval | 460 | (byte-compile-eval |
| @@ -459,7 +463,7 @@ Return the compile-time value of FORM." | |||
| 459 | (list 'quote result)))) | 463 | (list 'quote result)))) |
| 460 | (eval-and-compile . ,(lambda (&rest body) | 464 | (eval-and-compile . ,(lambda (&rest body) |
| 461 | (byte-compile-recurse-toplevel | 465 | (byte-compile-recurse-toplevel |
| 462 | (cons 'progn body) | 466 | (macroexp-progn body) |
| 463 | (lambda (form) | 467 | (lambda (form) |
| 464 | ;; Don't compile here, since we don't know | 468 | ;; Don't compile here, since we don't know |
| 465 | ;; whether to compile as byte-compile-form | 469 | ;; whether to compile as byte-compile-form |
| @@ -1458,7 +1462,7 @@ extra args." | |||
| 1458 | ;; These would sometimes be warned about | 1462 | ;; These would sometimes be warned about |
| 1459 | ;; but such warnings are never useful, | 1463 | ;; but such warnings are never useful, |
| 1460 | ;; so don't warn about them. | 1464 | ;; so don't warn about them. |
| 1461 | macroexpand cl-macroexpand-all | 1465 | macroexpand |
| 1462 | cl--compiling-file)))) | 1466 | cl--compiling-file)))) |
| 1463 | (byte-compile-warn "function `%s' from cl package called at runtime" | 1467 | (byte-compile-warn "function `%s' from cl package called at runtime" |
| 1464 | func))) | 1468 | func))) |
| @@ -2319,10 +2323,12 @@ list that represents a doc string reference. | |||
| 2319 | form)) | 2323 | form)) |
| 2320 | 2324 | ||
| 2321 | (put 'define-abbrev-table 'byte-hunk-handler | 2325 | (put 'define-abbrev-table 'byte-hunk-handler |
| 2322 | 'byte-compile-file-form-define-abbrev-table) | 2326 | 'byte-compile-file-form-defvar-function) |
| 2323 | (defun byte-compile-file-form-define-abbrev-table (form) | 2327 | (put 'defvaralias 'byte-hunk-handler 'byte-compile-file-form-defvar-function) |
| 2324 | (if (eq 'quote (car-safe (car-safe (cdr form)))) | 2328 | |
| 2325 | (byte-compile--declare-var (car-safe (cdr (cadr form))))) | 2329 | (defun byte-compile-file-form-defvar-function (form) |
| 2330 | (pcase-let (((or `',name (let name nil)) (nth 1 form))) | ||
| 2331 | (if name (byte-compile--declare-var name))) | ||
| 2326 | (byte-compile-keep-pending form)) | 2332 | (byte-compile-keep-pending form)) |
| 2327 | 2333 | ||
| 2328 | (put 'custom-declare-variable 'byte-hunk-handler | 2334 | (put 'custom-declare-variable 'byte-hunk-handler |
| @@ -2330,8 +2336,7 @@ list that represents a doc string reference. | |||
| 2330 | (defun byte-compile-file-form-custom-declare-variable (form) | 2336 | (defun byte-compile-file-form-custom-declare-variable (form) |
| 2331 | (when (byte-compile-warning-enabled-p 'callargs) | 2337 | (when (byte-compile-warning-enabled-p 'callargs) |
| 2332 | (byte-compile-nogroup-warn form)) | 2338 | (byte-compile-nogroup-warn form)) |
| 2333 | (byte-compile--declare-var (nth 1 (nth 1 form))) | 2339 | (byte-compile-file-form-defvar-function form)) |
| 2334 | (byte-compile-keep-pending form)) | ||
| 2335 | 2340 | ||
| 2336 | (put 'require 'byte-hunk-handler 'byte-compile-file-form-require) | 2341 | (put 'require 'byte-hunk-handler 'byte-compile-file-form-require) |
| 2337 | (defun byte-compile-file-form-require (form) | 2342 | (defun byte-compile-file-form-require (form) |
| @@ -2580,17 +2585,11 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2580 | fun) | 2585 | fun) |
| 2581 | (t | 2586 | (t |
| 2582 | (when (symbolp form) | 2587 | (when (symbolp form) |
| 2583 | (unless (memq (car-safe fun) '(closure lambda)) | ||
| 2584 | (error "Don't know how to compile %S" fun)) | ||
| 2585 | (setq lexical-binding (eq (car fun) 'closure)) | 2588 | (setq lexical-binding (eq (car fun) 'closure)) |
| 2586 | (setq fun (byte-compile--reify-function fun))) | 2589 | (setq fun (byte-compile--reify-function fun))) |
| 2587 | (unless (eq (car-safe fun) 'lambda) | ||
| 2588 | (error "Don't know how to compile %S" fun)) | ||
| 2589 | ;; Expand macros. | 2590 | ;; Expand macros. |
| 2590 | (setq fun (byte-compile-preprocess fun)) | 2591 | (setq fun (byte-compile-preprocess fun)) |
| 2591 | ;; Get rid of the `function' quote added by the `lambda' macro. | 2592 | (setq fun (byte-compile-top-level fun nil 'eval)) |
| 2592 | (if (eq (car-safe fun) 'function) (setq fun (cadr fun))) | ||
| 2593 | (setq fun (byte-compile-lambda fun)) | ||
| 2594 | (if macro (push 'macro fun)) | 2593 | (if macro (push 'macro fun)) |
| 2595 | (if (symbolp form) | 2594 | (if (symbolp form) |
| 2596 | (fset form fun) | 2595 | (fset form fun) |
| @@ -2966,6 +2965,16 @@ for symbols generated by the byte compiler itself." | |||
| 2966 | (interactive-only | 2965 | (interactive-only |
| 2967 | (or (get fn 'interactive-only) | 2966 | (or (get fn 'interactive-only) |
| 2968 | (memq fn byte-compile-interactive-only-functions)))) | 2967 | (memq fn byte-compile-interactive-only-functions)))) |
| 2968 | (when (memq fn '(set symbol-value run-hooks ;; add-to-list | ||
| 2969 | add-hook remove-hook run-hook-with-args | ||
| 2970 | run-hook-with-args-until-success | ||
| 2971 | run-hook-with-args-until-failure)) | ||
| 2972 | (pcase (cdr form) | ||
| 2973 | (`(',var . ,_) | ||
| 2974 | (when (assq var byte-compile-lexical-variables) | ||
| 2975 | (byte-compile-log-warning | ||
| 2976 | (format "%s cannot use lexical var `%s'" fn var) | ||
| 2977 | nil :error))))) | ||
| 2969 | (when (macroexp--const-symbol-p fn) | 2978 | (when (macroexp--const-symbol-p fn) |
| 2970 | (byte-compile-warn "`%s' called as a function" fn)) | 2979 | (byte-compile-warn "`%s' called as a function" fn)) |
| 2971 | (when (and (byte-compile-warning-enabled-p 'interactive-only) | 2980 | (when (and (byte-compile-warning-enabled-p 'interactive-only) |
| @@ -3079,8 +3088,9 @@ for symbols generated by the byte compiler itself." | |||
| 3079 | (dotimes (_ (- (/ (1+ fmax2) 2) alen)) | 3088 | (dotimes (_ (- (/ (1+ fmax2) 2) alen)) |
| 3080 | (byte-compile-push-constant nil))) | 3089 | (byte-compile-push-constant nil))) |
| 3081 | ((zerop (logand fmax2 1)) | 3090 | ((zerop (logand fmax2 1)) |
| 3082 | (byte-compile-log-warning "Too many arguments for inlined function" | 3091 | (byte-compile-log-warning |
| 3083 | nil :error) | 3092 | (format "Too many arguments for inlined function %S" form) |
| 3093 | nil :error) | ||
| 3084 | (byte-compile-discard (- alen (/ fmax2 2)))) | 3094 | (byte-compile-discard (- alen (/ fmax2 2)))) |
| 3085 | (t | 3095 | (t |
| 3086 | ;; Turn &rest args into a list. | 3096 | ;; Turn &rest args into a list. |
| @@ -3453,15 +3463,22 @@ discarding." | |||
| 3453 | (if byte-compile--for-effect (setq byte-compile--for-effect nil) | 3463 | (if byte-compile--for-effect (setq byte-compile--for-effect nil) |
| 3454 | (let* ((vars (nth 1 form)) | 3464 | (let* ((vars (nth 1 form)) |
| 3455 | (env (nth 2 form)) | 3465 | (env (nth 2 form)) |
| 3456 | (body (nthcdr 3 form)) | 3466 | (docstring-exp (nth 3 form)) |
| 3467 | (body (nthcdr 4 form)) | ||
| 3457 | (fun | 3468 | (fun |
| 3458 | (byte-compile-lambda `(lambda ,vars . ,body) nil (length env)))) | 3469 | (byte-compile-lambda `(lambda ,vars . ,body) nil (length env)))) |
| 3459 | (cl-assert (> (length env) 0)) ;Otherwise, we don't need a closure. | 3470 | (cl-assert (or (> (length env) 0) |
| 3471 | docstring-exp)) ;Otherwise, we don't need a closure. | ||
| 3460 | (cl-assert (byte-code-function-p fun)) | 3472 | (cl-assert (byte-code-function-p fun)) |
| 3461 | (byte-compile-form `(make-byte-code | 3473 | (byte-compile-form `(make-byte-code |
| 3462 | ',(aref fun 0) ',(aref fun 1) | 3474 | ',(aref fun 0) ',(aref fun 1) |
| 3463 | (vconcat (vector . ,env) ',(aref fun 2)) | 3475 | (vconcat (vector . ,env) ',(aref fun 2)) |
| 3464 | ,@(nthcdr 3 (mapcar (lambda (x) `',x) fun))))))) | 3476 | ,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) fun)))) |
| 3477 | (if docstring-exp | ||
| 3478 | `(,(car rest) | ||
| 3479 | ,docstring-exp | ||
| 3480 | ,@(cddr rest)) | ||
| 3481 | rest))))))) | ||
| 3465 | 3482 | ||
| 3466 | (defun byte-compile-get-closed-var (form) | 3483 | (defun byte-compile-get-closed-var (form) |
| 3467 | "Byte-compile the special `internal-get-closed-var' form." | 3484 | "Byte-compile the special `internal-get-closed-var' form." |
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index e9d33e6c646..fa824075933 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | ;; if the function is suitable for lambda lifting (if all calls are known) | 48 | ;; if the function is suitable for lambda lifting (if all calls are known) |
| 49 | ;; | 49 | ;; |
| 50 | ;; (lambda (v0 ...) ... fv0 .. fv1 ...) => | 50 | ;; (lambda (v0 ...) ... fv0 .. fv1 ...) => |
| 51 | ;; (internal-make-closure (v0 ...) (fv1 ...) | 51 | ;; (internal-make-closure (v0 ...) (fv0 ...) <doc> |
| 52 | ;; ... (internal-get-closed-var 0) ... (internal-get-closed-var 1) ...) | 52 | ;; ... (internal-get-closed-var 0) ... (internal-get-closed-var 1) ...) |
| 53 | ;; | 53 | ;; |
| 54 | ;; If the function has no free variables, we don't do anything. | 54 | ;; If the function has no free variables, we don't do anything. |
| @@ -65,6 +65,14 @@ | |||
| 65 | ;; | 65 | ;; |
| 66 | ;;; Code: | 66 | ;;; Code: |
| 67 | 67 | ||
| 68 | ;; PROBLEM cases found during conversion to lexical binding. | ||
| 69 | ;; We should try and detect and warn about those cases, even | ||
| 70 | ;; for lexical-binding==nil to help prepare the migration. | ||
| 71 | ;; - Uses of run-hooks, and friends. | ||
| 72 | ;; - Cases where we want to apply the same code to different vars depending on | ||
| 73 | ;; some test. These sometimes use a (let ((foo (if bar 'a 'b))) | ||
| 74 | ;; ... (symbol-value foo) ... (set foo ...)). | ||
| 75 | |||
| 68 | ;; TODO: (not just for cconv but also for the lexbind changes in general) | 76 | ;; TODO: (not just for cconv but also for the lexbind changes in general) |
| 69 | ;; - let (e)debug find the value of lexical variables from the stack. | 77 | ;; - let (e)debug find the value of lexical variables from the stack. |
| 70 | ;; - make eval-region do the eval-sexp-add-defvars dance. | 78 | ;; - make eval-region do the eval-sexp-add-defvars dance. |
| @@ -87,9 +95,8 @@ | |||
| 87 | ;; the bytecomp only compiles it once. | 95 | ;; the bytecomp only compiles it once. |
| 88 | ;; - Since we know here when a variable is not mutated, we could pass that | 96 | ;; - Since we know here when a variable is not mutated, we could pass that |
| 89 | ;; info to the byte-compiler, e.g. by using a new `immutable-let'. | 97 | ;; info to the byte-compiler, e.g. by using a new `immutable-let'. |
| 90 | ;; - add tail-calls to bytecode.c and the byte compiler. | ||
| 91 | ;; - call known non-escaping functions with `goto' rather than `call'. | 98 | ;; - call known non-escaping functions with `goto' rather than `call'. |
| 92 | ;; - optimize mapcar to a while loop. | 99 | ;; - optimize mapc to a dolist loop. |
| 93 | 100 | ||
| 94 | ;; (defmacro dlet (binders &rest body) | 101 | ;; (defmacro dlet (binders &rest body) |
| 95 | ;; ;; Works in both lexical and non-lexical mode. | 102 | ;; ;; Works in both lexical and non-lexical mode. |
| @@ -195,7 +202,7 @@ Returns a form where all lambdas don't have any free variables." | |||
| 195 | (unless (memq (car b) s) (push b res))) | 202 | (unless (memq (car b) s) (push b res))) |
| 196 | (nreverse res))) | 203 | (nreverse res))) |
| 197 | 204 | ||
| 198 | (defun cconv--convert-function (args body env parentform) | 205 | (defun cconv--convert-function (args body env parentform &optional docstring) |
| 199 | (cl-assert (equal body (caar cconv-freevars-alist))) | 206 | (cl-assert (equal body (caar cconv-freevars-alist))) |
| 200 | (let* ((fvs (cdr (pop cconv-freevars-alist))) | 207 | (let* ((fvs (cdr (pop cconv-freevars-alist))) |
| 201 | (body-new '()) | 208 | (body-new '()) |
| @@ -240,11 +247,11 @@ Returns a form where all lambdas don't have any free variables." | |||
| 240 | `(,@(nreverse special-forms) (let ,letbind . ,body-new))))) | 247 | `(,@(nreverse special-forms) (let ,letbind . ,body-new))))) |
| 241 | 248 | ||
| 242 | (cond | 249 | (cond |
| 243 | ((null envector) ;if no freevars - do nothing | 250 | ((not (or envector docstring)) ;If no freevars - do nothing. |
| 244 | `(function (lambda ,args . ,body-new))) | 251 | `(function (lambda ,args . ,body-new))) |
| 245 | (t | 252 | (t |
| 246 | `(internal-make-closure | 253 | `(internal-make-closure |
| 247 | ,args ,envector . ,body-new))))) | 254 | ,args ,envector ,docstring . ,body-new))))) |
| 248 | 255 | ||
| 249 | (defun cconv-convert (form env extend) | 256 | (defun cconv-convert (form env extend) |
| 250 | ;; This function actually rewrites the tree. | 257 | ;; This function actually rewrites the tree. |
| @@ -407,7 +414,9 @@ places where they originally did not directly appear." | |||
| 407 | cond-forms))) | 414 | cond-forms))) |
| 408 | 415 | ||
| 409 | (`(function (lambda ,args . ,body) . ,_) | 416 | (`(function (lambda ,args . ,body) . ,_) |
| 410 | (cconv--convert-function args body env form)) | 417 | (let ((docstring (if (eq :documentation (car-safe (car body))) |
| 418 | (cconv-convert (cadr (pop body)) env extend)))) | ||
| 419 | (cconv--convert-function args body env form docstring))) | ||
| 411 | 420 | ||
| 412 | (`(internal-make-closure . ,_) | 421 | (`(internal-make-closure . ,_) |
| 413 | (byte-compile-report-error | 422 | (byte-compile-report-error |
| @@ -533,7 +542,7 @@ FORM is the parent form that binds this var." | |||
| 533 | ;; use = `(,binder ,read ,mutated ,captured ,called) | 542 | ;; use = `(,binder ,read ,mutated ,captured ,called) |
| 534 | (pcase vardata | 543 | (pcase vardata |
| 535 | (`(,_ nil nil nil nil) nil) | 544 | (`(,_ nil nil nil nil) nil) |
| 536 | (`((,(and (pred (lambda (var) (eq ?_ (aref (symbol-name var) 0)))) var) . ,_) | 545 | (`((,(and var (guard (eq ?_ (aref (symbol-name var) 0)))) . ,_) |
| 537 | ,_ ,_ ,_ ,_) | 546 | ,_ ,_ ,_ ,_) |
| 538 | (byte-compile-log-warning | 547 | (byte-compile-log-warning |
| 539 | (format "%s `%S' not left unused" varkind var)))) | 548 | (format "%s `%S' not left unused" varkind var)))) |
| @@ -643,6 +652,8 @@ and updates the data stored in ENV." | |||
| 643 | (cconv--analyze-use vardata form "variable")))) | 652 | (cconv--analyze-use vardata form "variable")))) |
| 644 | 653 | ||
| 645 | (`(function (lambda ,vrs . ,body-forms)) | 654 | (`(function (lambda ,vrs . ,body-forms)) |
| 655 | (when (eq :documentation (car-safe (car body-forms))) | ||
| 656 | (cconv-analyze-form (cadr (pop body-forms)) env)) | ||
| 646 | (cconv--analyze-function vrs body-forms env form)) | 657 | (cconv--analyze-function vrs body-forms env form)) |
| 647 | 658 | ||
| 648 | (`(setq . ,forms) | 659 | (`(setq . ,forms) |
| @@ -665,6 +676,10 @@ and updates the data stored in ENV." | |||
| 665 | (dolist (forms cond-forms) | 676 | (dolist (forms cond-forms) |
| 666 | (dolist (form forms) (cconv-analyze-form form env)))) | 677 | (dolist (form forms) (cconv-analyze-form form env)))) |
| 667 | 678 | ||
| 679 | ;; ((and `(quote ,v . ,_) (guard (assq v env))) | ||
| 680 | ;; (byte-compile-log-warning | ||
| 681 | ;; (format "Possible confusion variable/symbol for `%S'" v))) | ||
| 682 | |||
| 668 | (`(quote . ,_) nil) ; quote form | 683 | (`(quote . ,_) nil) ; quote form |
| 669 | (`(function . ,_) nil) ; same as quote | 684 | (`(function . ,_) nil) ; same as quote |
| 670 | 685 | ||
diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el index 46585ee76c6..fcf02b92736 100644 --- a/lisp/emacs-lisp/eieio-base.el +++ b/lisp/emacs-lisp/eieio-base.el | |||
| @@ -290,8 +290,7 @@ constructor functions are considered valid. | |||
| 290 | Second, any text properties will be stripped from strings." | 290 | Second, any text properties will be stripped from strings." |
| 291 | (cond ((consp proposed-value) | 291 | (cond ((consp proposed-value) |
| 292 | ;; Lists with something in them need special treatment. | 292 | ;; Lists with something in them need special treatment. |
| 293 | (let ((slot-idx (eieio--slot-name-index class | 293 | (let ((slot-idx (eieio--slot-name-index class slot)) |
| 294 | nil slot)) | ||
| 295 | (type nil) | 294 | (type nil) |
| 296 | (classtype nil)) | 295 | (classtype nil)) |
| 297 | (setq slot-idx (- slot-idx | 296 | (setq slot-idx (- slot-idx |
diff --git a/lisp/emacs-lisp/eieio-compat.el b/lisp/emacs-lisp/eieio-compat.el index fcca99d79d5..7468c040e10 100644 --- a/lisp/emacs-lisp/eieio-compat.el +++ b/lisp/emacs-lisp/eieio-compat.el | |||
| @@ -188,11 +188,10 @@ Summary: | |||
| 188 | (args (help-function-arglist code 'preserve-names)) | 188 | (args (help-function-arglist code 'preserve-names)) |
| 189 | (doc-only (if docstring | 189 | (doc-only (if docstring |
| 190 | (let ((split (help-split-fundoc docstring nil))) | 190 | (let ((split (help-split-fundoc docstring nil))) |
| 191 | (if split (cdr split) docstring)))) | 191 | (if split (cdr split) docstring))))) |
| 192 | (new-docstring (help-add-fundoc-usage doc-only | ||
| 193 | (cons 'cl-cnm args)))) | ||
| 194 | ;; FIXME: ¡Add new-docstring to those closures! | ||
| 195 | (lambda (cnm &rest args) | 192 | (lambda (cnm &rest args) |
| 193 | (:documentation | ||
| 194 | (help-add-fundoc-usage doc-only (cons 'cl-cnm args))) | ||
| 196 | (cl-letf (((symbol-function 'call-next-method) cnm) | 195 | (cl-letf (((symbol-function 'call-next-method) cnm) |
| 197 | ((symbol-function 'next-method-p) | 196 | ((symbol-function 'next-method-p) |
| 198 | (lambda () (cl--generic-isnot-nnm-p cnm)))) | 197 | (lambda () (cl--generic-isnot-nnm-p cnm)))) |
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index 77d8c01388b..fa8fefa1df0 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el | |||
| @@ -288,16 +288,17 @@ It creates an autoload function for CNAME's constructor." | |||
| 288 | 288 | ||
| 289 | (defun eieio-make-class-predicate (class) | 289 | (defun eieio-make-class-predicate (class) |
| 290 | (lambda (obj) | 290 | (lambda (obj) |
| 291 | ;; (:docstring (format "Test OBJ to see if it's an object of type %S." | 291 | (:documentation |
| 292 | ;; class)) | 292 | (format "Return non-nil if OBJ is an object of type `%S'.\n\n(fn OBJ)" |
| 293 | class)) | ||
| 293 | (and (eieio-object-p obj) | 294 | (and (eieio-object-p obj) |
| 294 | (same-class-p obj class)))) | 295 | (same-class-p obj class)))) |
| 295 | 296 | ||
| 296 | (defun eieio-make-child-predicate (class) | 297 | (defun eieio-make-child-predicate (class) |
| 297 | (lambda (obj) | 298 | (lambda (obj) |
| 298 | ;; (:docstring (format | 299 | (:documentation |
| 299 | ;; "Test OBJ to see if it's an object is a child of type %S." | 300 | (format "Return non-nil if OBJ is an object of type `%S' or a subclass. |
| 300 | ;; class)) | 301 | \n(fn OBJ)" class)) |
| 301 | (and (eieio-object-p obj) | 302 | (and (eieio-object-p obj) |
| 302 | (object-of-class-p obj class)))) | 303 | (object-of-class-p obj class)))) |
| 303 | 304 | ||
| @@ -312,8 +313,7 @@ See `defclass' for more information." | |||
| 312 | (run-hooks 'eieio-hook) | 313 | (run-hooks 'eieio-hook) |
| 313 | (setq eieio-hook nil) | 314 | (setq eieio-hook nil) |
| 314 | 315 | ||
| 315 | (let* ((pname superclasses) | 316 | (let* ((oldc (let ((c (eieio--class-v cname))) (if (eieio--class-p c) c))) |
| 316 | (oldc (let ((c (eieio--class-v cname))) (if (eieio--class-p c) c))) | ||
| 317 | (newc (if (and oldc (not (eieio--class-default-object-cache oldc))) | 317 | (newc (if (and oldc (not (eieio--class-default-object-cache oldc))) |
| 318 | ;; The oldc class is a stub setup by eieio-defclass-autoload. | 318 | ;; The oldc class is a stub setup by eieio-defclass-autoload. |
| 319 | ;; Reuse it instead of creating a new one, so that existing | 319 | ;; Reuse it instead of creating a new one, so that existing |
| @@ -338,9 +338,9 @@ See `defclass' for more information." | |||
| 338 | (setf (eieio--class-children newc) children) | 338 | (setf (eieio--class-children newc) children) |
| 339 | (remhash cname eieio-defclass-autoload-map)))) | 339 | (remhash cname eieio-defclass-autoload-map)))) |
| 340 | 340 | ||
| 341 | (if pname | 341 | (if superclasses |
| 342 | (progn | 342 | (progn |
| 343 | (dolist (p pname) | 343 | (dolist (p superclasses) |
| 344 | (if (not (and p (symbolp p))) | 344 | (if (not (and p (symbolp p))) |
| 345 | (error "Invalid parent class %S" p) | 345 | (error "Invalid parent class %S" p) |
| 346 | (let ((c (eieio--class-v p))) | 346 | (let ((c (eieio--class-v p))) |
| @@ -396,7 +396,7 @@ See `defclass' for more information." | |||
| 396 | 396 | ||
| 397 | ;; Before adding new slots, let's add all the methods and classes | 397 | ;; Before adding new slots, let's add all the methods and classes |
| 398 | ;; in from the parent class. | 398 | ;; in from the parent class. |
| 399 | (eieio-copy-parents-into-subclass newc superclasses) | 399 | (eieio-copy-parents-into-subclass newc) |
| 400 | 400 | ||
| 401 | ;; Store the new class vector definition into the symbol. We need to | 401 | ;; Store the new class vector definition into the symbol. We need to |
| 402 | ;; do this first so that we can call defmethod for the accessor. | 402 | ;; do this first so that we can call defmethod for the accessor. |
| @@ -784,7 +784,7 @@ if default value is nil." | |||
| 784 | )) | 784 | )) |
| 785 | )) | 785 | )) |
| 786 | 786 | ||
| 787 | (defun eieio-copy-parents-into-subclass (newc _parents) | 787 | (defun eieio-copy-parents-into-subclass (newc) |
| 788 | "Copy into NEWC the slots of PARENTS. | 788 | "Copy into NEWC the slots of PARENTS. |
| 789 | Follow the rules of not overwriting early parents when applying to | 789 | Follow the rules of not overwriting early parents when applying to |
| 790 | the new child class." | 790 | the new child class." |
| @@ -911,7 +911,7 @@ Argument FN is the function calling this verifier." | |||
| 911 | (if (eieio--class-p c) (eieio-class-un-autoload obj)) | 911 | (if (eieio--class-p c) (eieio-class-un-autoload obj)) |
| 912 | c)) | 912 | c)) |
| 913 | (t (eieio--object-class-object obj)))) | 913 | (t (eieio--object-class-object obj)))) |
| 914 | (c (eieio--slot-name-index class obj slot))) | 914 | (c (eieio--slot-name-index class slot))) |
| 915 | (if (not c) | 915 | (if (not c) |
| 916 | ;; It might be missing because it is a :class allocated slot. | 916 | ;; It might be missing because it is a :class allocated slot. |
| 917 | ;; Let's check that info out. | 917 | ;; Let's check that info out. |
| @@ -935,7 +935,7 @@ Fills in OBJ's SLOT with its default value." | |||
| 935 | (cl-check-type slot symbol) | 935 | (cl-check-type slot symbol) |
| 936 | (let* ((cl (cond ((symbolp obj) (eieio--class-v obj)) | 936 | (let* ((cl (cond ((symbolp obj) (eieio--class-v obj)) |
| 937 | (t (eieio--object-class-object obj)))) | 937 | (t (eieio--object-class-object obj)))) |
| 938 | (c (eieio--slot-name-index cl obj slot))) | 938 | (c (eieio--slot-name-index cl slot))) |
| 939 | (if (not c) | 939 | (if (not c) |
| 940 | ;; It might be missing because it is a :class allocated slot. | 940 | ;; It might be missing because it is a :class allocated slot. |
| 941 | ;; Let's check that info out. | 941 | ;; Let's check that info out. |
| @@ -973,7 +973,7 @@ Fills in OBJ's SLOT with VALUE." | |||
| 973 | (cl-check-type obj eieio-object) | 973 | (cl-check-type obj eieio-object) |
| 974 | (cl-check-type slot symbol) | 974 | (cl-check-type slot symbol) |
| 975 | (let* ((class (eieio--object-class-object obj)) | 975 | (let* ((class (eieio--object-class-object obj)) |
| 976 | (c (eieio--slot-name-index class obj slot))) | 976 | (c (eieio--slot-name-index class slot))) |
| 977 | (if (not c) | 977 | (if (not c) |
| 978 | ;; It might be missing because it is a :class allocated slot. | 978 | ;; It might be missing because it is a :class allocated slot. |
| 979 | ;; Let's check that info out. | 979 | ;; Let's check that info out. |
| @@ -997,7 +997,7 @@ Fills in the default value in CLASS' in SLOT with VALUE." | |||
| 997 | (setq class (eieio--class-object class)) | 997 | (setq class (eieio--class-object class)) |
| 998 | (cl-check-type class eieio--class) | 998 | (cl-check-type class eieio--class) |
| 999 | (cl-check-type slot symbol) | 999 | (cl-check-type slot symbol) |
| 1000 | (let* ((c (eieio--slot-name-index class nil slot))) | 1000 | (let* ((c (eieio--slot-name-index class slot))) |
| 1001 | (if (not c) | 1001 | (if (not c) |
| 1002 | ;; It might be missing because it is a :class allocated slot. | 1002 | ;; It might be missing because it is a :class allocated slot. |
| 1003 | ;; Let's check that info out. | 1003 | ;; Let's check that info out. |
| @@ -1021,12 +1021,9 @@ Fills in the default value in CLASS' in SLOT with VALUE." | |||
| 1021 | 1021 | ||
| 1022 | ;;; EIEIO internal search functions | 1022 | ;;; EIEIO internal search functions |
| 1023 | ;; | 1023 | ;; |
| 1024 | (defun eieio--slot-name-index (class obj slot) | 1024 | (defun eieio--slot-name-index (class slot) |
| 1025 | "In CLASS for OBJ find the index of the named SLOT. | 1025 | "In CLASS find the index of the named SLOT. |
| 1026 | The slot is a symbol which is installed in CLASS by the `defclass' | 1026 | The slot is a symbol which is installed in CLASS by the `defclass' call. |
| 1027 | call. OBJ can be nil, but if it is an object, and the slot in question | ||
| 1028 | is protected, access will be allowed if OBJ is a child of the currently | ||
| 1029 | scoped class. | ||
| 1030 | If SLOT is the value created with :initarg instead, | 1027 | If SLOT is the value created with :initarg instead, |
| 1031 | reverse-lookup that name, and recurse with the associated slot value." | 1028 | reverse-lookup that name, and recurse with the associated slot value." |
| 1032 | ;; Removed checks to outside this call | 1029 | ;; Removed checks to outside this call |
| @@ -1035,7 +1032,7 @@ reverse-lookup that name, and recurse with the associated slot value." | |||
| 1035 | (if (integerp fsi) | 1032 | (if (integerp fsi) |
| 1036 | (+ (eval-when-compile eieio--object-num-slots) fsi) | 1033 | (+ (eval-when-compile eieio--object-num-slots) fsi) |
| 1037 | (let ((fn (eieio--initarg-to-attribute class slot))) | 1034 | (let ((fn (eieio--initarg-to-attribute class slot))) |
| 1038 | (if fn (eieio--slot-name-index class obj fn) nil))))) | 1035 | (if fn (eieio--slot-name-index class fn) nil))))) |
| 1039 | 1036 | ||
| 1040 | (defun eieio--class-slot-name-index (class slot) | 1037 | (defun eieio--class-slot-name-index (class slot) |
| 1041 | "In CLASS find the index of the named SLOT. | 1038 | "In CLASS find the index of the named SLOT. |
| @@ -1255,7 +1252,7 @@ method invocation orders of the involved classes." | |||
| 1255 | (eieio--class-precedence-list tag)))) | 1252 | (eieio--class-precedence-list tag)))) |
| 1256 | 1253 | ||
| 1257 | 1254 | ||
| 1258 | ;;;### (autoloads nil "eieio-compat" "eieio-compat.el" "b568ffb3c90ed5d0ae673f0051d608ee") | 1255 | ;;;### (autoloads nil "eieio-compat" "eieio-compat.el" "5b04c9a8fff2bd3f3d3ac54aba0f65b7") |
| 1259 | ;;; Generated autoloads from eieio-compat.el | 1256 | ;;; Generated autoloads from eieio-compat.el |
| 1260 | 1257 | ||
| 1261 | (autoload 'eieio--defalias "eieio-compat" "\ | 1258 | (autoload 'eieio--defalias "eieio-compat" "\ |
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 67cd44d6758..c3a2061aae2 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -161,6 +161,7 @@ | |||
| 161 | 161 | ||
| 162 | ;;; Code: | 162 | ;;; Code: |
| 163 | 163 | ||
| 164 | (eval-when-compile (require 'subr-x)) | ||
| 164 | (eval-when-compile (require 'cl-lib)) | 165 | (eval-when-compile (require 'cl-lib)) |
| 165 | (eval-when-compile (require 'epg)) ;For setf accessors. | 166 | (eval-when-compile (require 'epg)) ;For setf accessors. |
| 166 | 167 | ||
| @@ -1510,6 +1511,11 @@ with PKG-DESC entry removed." | |||
| 1510 | (and (memq pkg (mapcar #'car (package-desc-reqs (cadr p)))) | 1511 | (and (memq pkg (mapcar #'car (package-desc-reqs (cadr p)))) |
| 1511 | (car p)))))) | 1512 | (car p)))))) |
| 1512 | 1513 | ||
| 1514 | (defun package--newest-p (pkg) | ||
| 1515 | "Return t if PKG is the newest package with its name." | ||
| 1516 | (equal (cadr (assq (package-desc-name pkg) package-alist)) | ||
| 1517 | pkg)) | ||
| 1518 | |||
| 1513 | (defun package-delete (pkg-desc &optional force nosave) | 1519 | (defun package-delete (pkg-desc &optional force nosave) |
| 1514 | "Delete package PKG-DESC. | 1520 | "Delete package PKG-DESC. |
| 1515 | 1521 | ||
| @@ -1527,7 +1533,10 @@ If NOSAVE is non-nil, the package is not removed from | |||
| 1527 | ;; don't want it marked as selected, so we remove it from | 1533 | ;; don't want it marked as selected, so we remove it from |
| 1528 | ;; `package-selected-packages' even if it can't be deleted. | 1534 | ;; `package-selected-packages' even if it can't be deleted. |
| 1529 | (when (and (null nosave) | 1535 | (when (and (null nosave) |
| 1530 | (package--user-selected-p name)) | 1536 | (package--user-selected-p name) |
| 1537 | ;; Don't delesect if this is an older version of an | ||
| 1538 | ;; upgraded package. | ||
| 1539 | (package--newest-p pkg-desc)) | ||
| 1531 | (customize-save-variable | 1540 | (customize-save-variable |
| 1532 | 'package-selected-packages (remove name package-selected-packages))) | 1541 | 'package-selected-packages (remove name package-selected-packages))) |
| 1533 | (cond ((not (string-prefix-p (file-name-as-directory | 1542 | (cond ((not (string-prefix-p (file-name-as-directory |
| @@ -2262,7 +2271,7 @@ If optional arg BUTTON is non-nil, describe its associated package." | |||
| 2262 | (defun package-menu-mark-install (&optional _num) | 2271 | (defun package-menu-mark-install (&optional _num) |
| 2263 | "Mark a package for installation and move to the next line." | 2272 | "Mark a package for installation and move to the next line." |
| 2264 | (interactive "p") | 2273 | (interactive "p") |
| 2265 | (if (member (package-menu-get-status) '("available" "new")) | 2274 | (if (member (package-menu-get-status) '("available" "new" "dependency")) |
| 2266 | (tabulated-list-put-tag "I" t) | 2275 | (tabulated-list-put-tag "I" t) |
| 2267 | (forward-line))) | 2276 | (forward-line))) |
| 2268 | 2277 | ||
| @@ -2351,6 +2360,40 @@ call will upgrade the package." | |||
| 2351 | (length upgrades) | 2360 | (length upgrades) |
| 2352 | (if (= (length upgrades) 1) "" "s"))))) | 2361 | (if (= (length upgrades) 1) "" "s"))))) |
| 2353 | 2362 | ||
| 2363 | (defun package--sort-deps-in-alist (package only) | ||
| 2364 | "Return a list of dependencies for PACKAGE sorted by dependency. | ||
| 2365 | PACKAGE is included as the first element of the returned list. | ||
| 2366 | ONLY is an alist associating package names to package objects. | ||
| 2367 | Only these packages will be in the return value an their cdrs are | ||
| 2368 | destructively set to nil in ONLY." | ||
| 2369 | (let ((out)) | ||
| 2370 | (dolist (dep (package-desc-reqs package)) | ||
| 2371 | (when-let ((cell (assq (car dep) only)) | ||
| 2372 | (dep-package (cdr-safe cell))) | ||
| 2373 | (setcdr cell nil) | ||
| 2374 | (setq out (append (package--sort-deps-in-alist dep-package only) | ||
| 2375 | out)))) | ||
| 2376 | (cons package out))) | ||
| 2377 | |||
| 2378 | (defun package--sort-by-dependence (package-list) | ||
| 2379 | "Return PACKAGE-LIST sorted by dependence. | ||
| 2380 | That is, any element of the returned list is guaranteed to not | ||
| 2381 | directly depend on any elements that come before it. | ||
| 2382 | |||
| 2383 | PACKAGE-LIST is a list of package-desc objects. | ||
| 2384 | Indirect dependencies are guaranteed to be returned in order only | ||
| 2385 | if all the in-between dependencies are also in PACKAGE-LIST." | ||
| 2386 | (let ((alist (mapcar (lambda (p) (cons (package-desc-name p) p)) package-list)) | ||
| 2387 | out-list) | ||
| 2388 | (dolist (cell alist out-list) | ||
| 2389 | ;; `package--sort-deps-in-alist' destructively changes alist, so | ||
| 2390 | ;; some cells might already be empty. We check this here. | ||
| 2391 | (when-let ((pkg-desc (cdr cell))) | ||
| 2392 | (setcdr cell nil) | ||
| 2393 | (setq out-list | ||
| 2394 | (append (package--sort-deps-in-alist pkg-desc alist) | ||
| 2395 | out-list)))))) | ||
| 2396 | |||
| 2354 | (defun package-menu-execute (&optional noquery) | 2397 | (defun package-menu-execute (&optional noquery) |
| 2355 | "Perform marked Package Menu actions. | 2398 | "Perform marked Package Menu actions. |
| 2356 | Packages marked for installation are downloaded and installed; | 2399 | Packages marked for installation are downloaded and installed; |
| @@ -2384,7 +2427,13 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm." | |||
| 2384 | (mapconcat #'package-desc-full-name | 2427 | (mapconcat #'package-desc-full-name |
| 2385 | install-list ", "))))) | 2428 | install-list ", "))))) |
| 2386 | (mapc (lambda (p) | 2429 | (mapc (lambda (p) |
| 2387 | (package-install p (null (package-installed-p p)))) | 2430 | ;; Mark as selected if it's the exact version of a |
| 2431 | ;; package that's already installed, or if it's not | ||
| 2432 | ;; installed at all. Don't mark if it's a new | ||
| 2433 | ;; version of an installed package. | ||
| 2434 | (package-install p (or (package-installed-p p) | ||
| 2435 | (not (package-installed-p | ||
| 2436 | (package-desc-name p)))))) | ||
| 2388 | install-list))) | 2437 | install-list))) |
| 2389 | ;; Delete packages, prompting if necessary. | 2438 | ;; Delete packages, prompting if necessary. |
| 2390 | (when delete-list | 2439 | (when delete-list |
| @@ -2398,7 +2447,7 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm." | |||
| 2398 | (length delete-list) | 2447 | (length delete-list) |
| 2399 | (mapconcat #'package-desc-full-name | 2448 | (mapconcat #'package-desc-full-name |
| 2400 | delete-list ", "))))) | 2449 | delete-list ", "))))) |
| 2401 | (dolist (elt delete-list) | 2450 | (dolist (elt (package--sort-by-dependence delete-list)) |
| 2402 | (condition-case-unless-debug err | 2451 | (condition-case-unless-debug err |
| 2403 | (package-delete elt) | 2452 | (package-delete elt) |
| 2404 | (error (message (cadr err))))) | 2453 | (error (message (cadr err))))) |
| @@ -2412,7 +2461,8 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm." | |||
| 2412 | (format "These %d packages are no longer needed, delete them (%s)? " | 2461 | (format "These %d packages are no longer needed, delete them (%s)? " |
| 2413 | (length removable) | 2462 | (length removable) |
| 2414 | (mapconcat #'symbol-name removable ", ")))) | 2463 | (mapconcat #'symbol-name removable ", ")))) |
| 2415 | (mapc (lambda (p) (package-delete (cadr (assq p package-alist)))) | 2464 | ;; We know these are removable, so we can use force instead of sorting them. |
| 2465 | (mapc (lambda (p) (package-delete (cadr (assq p package-alist)) 'force 'nosave)) | ||
| 2416 | removable)))) | 2466 | removable)))) |
| 2417 | (package-menu--generate t t)))) | 2467 | (package-menu--generate t t)))) |
| 2418 | 2468 | ||
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index b28153b7f81..025d94e10b9 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el | |||
| @@ -2,9 +2,9 @@ | |||
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2014-2015 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2014-2015 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Nicolas Petton <petton.nicolas@gmail.com> | 5 | ;; Author: Nicolas Petton <nicolas@petton.fr> |
| 6 | ;; Keywords: sequences | 6 | ;; Keywords: sequences |
| 7 | ;; Version: 1.0 | 7 | ;; Version: 1.1 |
| 8 | 8 | ||
| 9 | ;; Maintainer: emacs-devel@gnu.org | 9 | ;; Maintainer: emacs-devel@gnu.org |
| 10 | 10 | ||
| @@ -92,14 +92,14 @@ returned." | |||
| 92 | (seq-subseq seq 0 (min (max n 0) (seq-length seq))))) | 92 | (seq-subseq seq 0 (min (max n 0) (seq-length seq))))) |
| 93 | 93 | ||
| 94 | (defun seq-drop-while (pred seq) | 94 | (defun seq-drop-while (pred seq) |
| 95 | "Return a sequence, from the first element for which (PRED element) is nil, of SEQ. | 95 | "Return a sequence from the first element for which (PRED element) is nil in SEQ. |
| 96 | The result is a sequence of the same type as SEQ." | 96 | The result is a sequence of the same type as SEQ." |
| 97 | (if (listp seq) | 97 | (if (listp seq) |
| 98 | (seq--drop-while-list pred seq) | 98 | (seq--drop-while-list pred seq) |
| 99 | (seq-drop seq (seq--count-successive pred seq)))) | 99 | (seq-drop seq (seq--count-successive pred seq)))) |
| 100 | 100 | ||
| 101 | (defun seq-take-while (pred seq) | 101 | (defun seq-take-while (pred seq) |
| 102 | "Return a sequence of the successive elements for which (PRED element) is non-nil in SEQ. | 102 | "Return the successive elements for which (PRED element) is non-nil in SEQ. |
| 103 | The result is a sequence of the same type as SEQ." | 103 | The result is a sequence of the same type as SEQ." |
| 104 | (if (listp seq) | 104 | (if (listp seq) |
| 105 | (seq--take-while-list pred seq) | 105 | (seq--take-while-list pred seq) |
| @@ -152,7 +152,7 @@ If SEQ is empty, return INITIAL-VALUE and FUNCTION is not called." | |||
| 152 | t)) | 152 | t)) |
| 153 | 153 | ||
| 154 | (defun seq-count (pred seq) | 154 | (defun seq-count (pred seq) |
| 155 | "Return the number of elements for which (PRED element) returns non-nil in seq." | 155 | "Return the number of elements for which (PRED element) is non-nil in SEQ." |
| 156 | (let ((count 0)) | 156 | (let ((count 0)) |
| 157 | (seq-doseq (elt seq) | 157 | (seq-doseq (elt seq) |
| 158 | (when (funcall pred elt) | 158 | (when (funcall pred elt) |
| @@ -224,15 +224,50 @@ TYPE must be one of following symbols: vector, string or list. | |||
| 224 | (`list (apply #'append (append seqs '(nil)))) | 224 | (`list (apply #'append (append seqs '(nil)))) |
| 225 | (t (error "Not a sequence type name: %s" type)))) | 225 | (t (error "Not a sequence type name: %s" type)))) |
| 226 | 226 | ||
| 227 | (defun seq-mapcat (function seq &optional type) | ||
| 228 | "Concatenate the result of applying FUNCTION to each element of SEQ. | ||
| 229 | The result is a sequence of type TYPE, or a list if TYPE is nil." | ||
| 230 | (apply #'seq-concatenate (or type 'list) | ||
| 231 | (seq-map function seq))) | ||
| 232 | |||
| 233 | (defun seq-partition (seq n) | ||
| 234 | "Return a list of the elements of SEQ grouped into sub-sequences of length N. | ||
| 235 | The last sequence may contain less than N elements. If N is a | ||
| 236 | negative integer or 0, nil is returned." | ||
| 237 | (unless (< n 1) | ||
| 238 | (let ((result '())) | ||
| 239 | (while (not (seq-empty-p seq)) | ||
| 240 | (push (seq-take seq n) result) | ||
| 241 | (setq seq (seq-drop seq n))) | ||
| 242 | (nreverse result)))) | ||
| 243 | |||
| 244 | (defun seq-group-by (function seq) | ||
| 245 | "Apply FUNCTION to each element of SEQ. | ||
| 246 | Separate the elements of SEQ into an alist using the results as | ||
| 247 | keys. Keys are compared using `equal'." | ||
| 248 | (nreverse | ||
| 249 | (seq-reduce | ||
| 250 | (lambda (acc elt) | ||
| 251 | (let* ((key (funcall function elt)) | ||
| 252 | (cell (assoc key acc))) | ||
| 253 | (if cell | ||
| 254 | (setcdr cell (push elt (cdr cell))) | ||
| 255 | (push (list key elt) acc)) | ||
| 256 | acc)) | ||
| 257 | seq | ||
| 258 | nil))) | ||
| 259 | |||
| 227 | (defun seq--drop-list (list n) | 260 | (defun seq--drop-list (list n) |
| 228 | "Optimized version of `seq-drop' for lists." | 261 | "Return a list from LIST without its first N elements. |
| 262 | This is an optimization for lists in `seq-drop'." | ||
| 229 | (while (and list (> n 0)) | 263 | (while (and list (> n 0)) |
| 230 | (setq list (cdr list) | 264 | (setq list (cdr list) |
| 231 | n (1- n))) | 265 | n (1- n))) |
| 232 | list) | 266 | list) |
| 233 | 267 | ||
| 234 | (defun seq--take-list (list n) | 268 | (defun seq--take-list (list n) |
| 235 | "Optimized version of `seq-take' for lists." | 269 | "Return a list from LIST made of its first N elements. |
| 270 | This is an optimization for lists in `seq-take'." | ||
| 236 | (let ((result '())) | 271 | (let ((result '())) |
| 237 | (while (and list (> n 0)) | 272 | (while (and list (> n 0)) |
| 238 | (setq n (1- n)) | 273 | (setq n (1- n)) |
| @@ -240,13 +275,15 @@ TYPE must be one of following symbols: vector, string or list. | |||
| 240 | (nreverse result))) | 275 | (nreverse result))) |
| 241 | 276 | ||
| 242 | (defun seq--drop-while-list (pred list) | 277 | (defun seq--drop-while-list (pred list) |
| 243 | "Optimized version of `seq-drop-while' for lists." | 278 | "Return a list from the first element for which (PRED element) is nil in LIST. |
| 279 | This is an optimization for lists in `seq-drop-while'." | ||
| 244 | (while (and list (funcall pred (car list))) | 280 | (while (and list (funcall pred (car list))) |
| 245 | (setq list (cdr list))) | 281 | (setq list (cdr list))) |
| 246 | list) | 282 | list) |
| 247 | 283 | ||
| 248 | (defun seq--take-while-list (pred list) | 284 | (defun seq--take-while-list (pred list) |
| 249 | "Optimized version of `seq-take-while' for lists." | 285 | "Return the successive elements for which (PRED element) is non-nil in LIST. |
| 286 | This is an optimization for lists in `seq-take-while'." | ||
| 250 | (let ((result '())) | 287 | (let ((result '())) |
| 251 | (while (and list (funcall pred (car list))) | 288 | (while (and list (funcall pred (car list))) |
| 252 | (push (pop list) result)) | 289 | (push (pop list) result)) |