mirrored from git://git.sv.gnu.org/emacs.git
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
subr.el
7557 lines (6668 loc) · 306 KB
/
subr.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; subr.el --- basic lisp subroutines for Emacs -*- lexical-binding:t -*-
;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: [email protected]
;; Keywords: internal
;; Package: emacs
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
;; declare-function's args use &rest, not &optional, for compatibility
;; with byte-compile-macroexpand-declare-function.
(defmacro declare-function (_fn _file &rest _args)
"Tell the byte-compiler that function FN is defined, in FILE.
The FILE argument is not used by the byte-compiler, but by the
`check-declare' package, which checks that FILE contains a
definition for FN. (FILE can be nil, and that disables this
check.)
FILE can be either a Lisp file (in which case the \".el\"
extension is optional), or a C file. C files are expanded
relative to the Emacs \"src/\" directory. Lisp files are
searched for using `locate-library', and if that fails they are
expanded relative to the location of the file containing the
declaration. A FILE with an \"ext:\" prefix is an external file.
`check-declare' will check such files if they are found, and skip
them without error if they are not.
Optional ARGLIST specifies FN's arguments, in the same form as
in `defun' (including the parentheses); or it is t to not specify
FN's arguments. An omitted ARGLIST defaults to t, not nil: a nil
ARGLIST specifies an empty argument list, and an explicit t
ARGLIST is a placeholder that allows supplying a later arg.
Optional FILEONLY non-nil means that `check-declare' will check
only that FILE exists, not that it defines FN. This is intended
for function definitions that `check-declare' does not recognize,
e.g., `defstruct'.
Note that for the purposes of `check-declare', this statement
must be the first non-whitespace on a line.
For more information, see Info node `(elisp)Declaring Functions'."
(declare (advertised-calling-convention
(fn file &optional arglist fileonly) nil))
;; Does nothing - `byte-compile-macroexpand-declare-function' does
;; the work.
nil)
;;;; Basic Lisp macros.
(defalias 'not #'null)
(defalias 'sxhash #'sxhash-equal)
(defmacro noreturn (form)
"Evaluate FORM, expecting it not to return.
If FORM does return, signal an error."
(declare (debug t))
`(prog1 ,form
(error "Form marked with `noreturn' did return")))
(defmacro 1value (form)
"Evaluate FORM, expecting a constant return value.
If FORM returns differing values when running under Testcover,
Testcover will raise an error."
(declare (debug t))
form)
(defmacro def-edebug-spec (symbol spec)
"Set the Edebug SPEC to use for sexps which have SYMBOL as head.
Both SYMBOL and SPEC are unevaluated. The SPEC can be:
0 (instrument no arguments); t (instrument all arguments);
a symbol (naming a function with an Edebug specification); or a list.
The elements of the list describe the argument types; see
Info node `(elisp)Specification List' for details."
(declare (indent 1))
`(put (quote ,symbol) 'edebug-form-spec (quote ,spec)))
(defun def-edebug-elem-spec (name spec)
"Define a new Edebug spec element NAME as shorthand for SPEC.
The SPEC has to be a list."
(declare (indent 1))
(when (string-match "\\`[&:]" (symbol-name name))
;; & and : have special meaning in spec element names.
(error "Edebug spec name cannot start with '&' or ':'"))
(unless (consp spec)
(error "Edebug spec has to be a list: %S" spec))
(put name 'edebug-elem-spec spec))
(defmacro lambda (&rest cdr)
"Return an anonymous function.
Under dynamic binding, a call of the form (lambda ARGS DOCSTRING
INTERACTIVE BODY) is self-quoting; the result of evaluating the
lambda expression is the expression itself. Under lexical
binding, the result is a closure. Regardless, the result is a
function, i.e., it may be stored as the function value of a
symbol, passed to `funcall' or `mapcar', etc.
ARGS should take the same form as an argument list for a `defun'.
DOCSTRING is an optional documentation string.
If present, it should describe how to call the function.
But documentation strings are usually not useful in nameless functions.
INTERACTIVE should be a call to the function `interactive', which see.
It may also be omitted.
BODY should be a list of Lisp expressions.
\(fn ARGS [DOCSTRING] [INTERACTIVE] BODY)"
(declare (doc-string 2) (indent defun)
(debug (&define lambda-list lambda-doc
[&optional ("interactive" interactive)]
def-body)))
;; Note that this definition should not use backquotes; subr.el should not
;; depend on backquote.el.
(list 'function (cons 'lambda cdr)))
(defmacro prog2 (form1 form2 &rest body)
"Eval FORM1, FORM2 and BODY sequentially; return value from FORM2.
The value of FORM2 is saved during the evaluation of the
remaining args, whose values are discarded."
(declare (indent 2) (debug t))
`(progn ,form1 (prog1 ,form2 ,@body)))
(defmacro setq-default (&rest args)
"Set the default value of variable VAR to VALUE.
VAR, the variable name, is literal (not evaluated);
VALUE is an expression: it is evaluated and its value returned.
The default value of a variable is seen in buffers
that do not have their own values for the variable.
More generally, you can use multiple variables and values, as in
(setq-default VAR VALUE VAR VALUE...)
This sets each VAR's default value to the corresponding VALUE.
The VALUE for the Nth VAR can refer to the new default values
of previous VARs.
\(fn [VAR VALUE]...)"
(declare (debug setq))
(let ((exps nil))
(while args
(push `(set-default ',(pop args) ,(pop args)) exps))
`(progn . ,(nreverse exps))))
(defmacro setq-local (&rest pairs)
"Make each VARIABLE buffer-local and assign to it the corresponding VALUE.
The arguments are variable/value pairs. For each VARIABLE in a pair,
make VARIABLE buffer-local and assign to it the corresponding VALUE
of the pair. The VARIABLEs are literal symbols and should not be quoted.
The VALUE of the Nth pair is not computed until after the VARIABLE
of the (N-1)th pair is set; thus, each VALUE can use the new VALUEs
of VARIABLEs set by earlier pairs.
The return value of the `setq-local' form is the VALUE of the last
pair.
\(fn [VARIABLE VALUE]...)"
(declare (debug setq))
(unless (zerop (mod (length pairs) 2))
(error "PAIRS must have an even number of variable/value members"))
(let ((expr nil))
(while pairs
(unless (symbolp (car pairs))
(error "Attempting to set a non-symbol: %s" (car pairs)))
;; Can't use backquote here, it's too early in the bootstrap.
(setq expr
(cons
(list 'set
(list 'make-local-variable (list 'quote (car pairs)))
(car (cdr pairs)))
expr))
(setq pairs (cdr (cdr pairs))))
(macroexp-progn (nreverse expr))))
(defmacro defvar-local (var val &optional docstring)
"Define VAR as a buffer-local variable with default value VAL.
Like `defvar' but additionally marks the variable as being automatically
buffer-local wherever it is set."
(declare (debug defvar) (doc-string 3) (indent 2))
;; Can't use backquote here, it's too early in the bootstrap.
(list 'progn (list 'defvar var val docstring)
(list 'make-variable-buffer-local (list 'quote var))))
(defun buffer-local-boundp (symbol buffer)
"Return non-nil if SYMBOL is bound in BUFFER.
Also see `local-variable-p'."
(declare (side-effect-free t))
(condition-case nil
(buffer-local-value symbol buffer)
(:success t)
(void-variable nil)))
(defmacro buffer-local-set-state (&rest pairs)
"Like `setq-local', but allow restoring the previous state of locals later.
This macro returns an object that can be passed to `buffer-local-restore-state'
in order to restore the state of the local variables set via this macro.
\(fn [VARIABLE VALUE]...)"
(declare (debug setq))
(unless (zerop (mod (length pairs) 2))
(error "PAIRS must have an even number of variable/value members"))
`(prog1
(buffer-local-set-state--get ',pairs)
(setq-local ,@pairs)))
(defun buffer-local-set-state--get (pairs)
(let ((states nil))
(while pairs
(push (list (car pairs)
(and (boundp (car pairs))
(local-variable-p (car pairs)))
(and (boundp (car pairs))
(symbol-value (car pairs))))
states)
(setq pairs (cddr pairs)))
(nreverse states)))
(defun buffer-local-restore-state (states)
"Restore values of buffer-local variables recorded in STATES.
STATES should be an object returned by `buffer-local-set-state'."
(pcase-dolist (`(,variable ,local ,value) states)
(if local
(set variable value)
(kill-local-variable variable))))
(defmacro push (newelt place)
"Add NEWELT to the list stored in the generalized variable PLACE.
This is morally equivalent to (setf PLACE (cons NEWELT PLACE)),
except that PLACE is evaluated only once (after NEWELT)."
(declare (debug (form gv-place)))
(if (symbolp place)
;; Important special case, to avoid triggering GV too early in
;; the bootstrap.
(list 'setq place
(list 'cons newelt place))
(require 'macroexp)
(macroexp-let2 macroexp-copyable-p x newelt
(gv-letplace (getter setter) place
(funcall setter `(cons ,x ,getter))))))
(defmacro pop (place)
"Return the first element of PLACE's value, and remove it from the list.
PLACE must be a generalized variable whose value is a list.
If the value is nil, `pop' returns nil but does not actually
change the list."
(declare (debug (gv-place)))
;; We use `car-safe' here instead of `car' because the behavior is the same
;; (if it's not a cons cell, the `cdr' would have signaled an error already),
;; but `car-safe' is total, so the byte-compiler can safely remove it if the
;; result is not used.
`(car-safe
,(if (symbolp place)
;; So we can use `pop' in the bootstrap before `gv' can be used.
(list 'prog1 place (list 'setq place (list 'cdr place)))
(gv-letplace (getter setter) place
(macroexp-let2 macroexp-copyable-p x getter
`(prog1 ,x ,(funcall setter `(cdr ,x))))))))
;; Note: `static-if' can be copied into a package to enable it to be
;; used in Emacsen older than Emacs 30.1. If the package is used in
;; very old Emacsen or XEmacs (in which `eval' takes exactly one
;; argument) the copy will need amending.
(defmacro static-if (condition then-form &rest else-forms)
"A conditional compilation macro.
Evaluate CONDITION at macro-expansion time. If it is non-nil,
expand the macro to THEN-FORM. Otherwise expand it to ELSE-FORMS
enclosed in a `progn' form. ELSE-FORMS may be empty."
(declare (indent 2)
(debug (sexp sexp &rest sexp)))
(if (eval condition lexical-binding)
then-form
(cons 'progn else-forms)))
(defmacro when (cond &rest body)
"If COND yields non-nil, do BODY, else return nil.
When COND yields non-nil, eval BODY forms sequentially and return
value of last one, or nil if there are none."
(declare (indent 1) (debug t))
(if body
(list 'if cond (cons 'progn body))
(macroexp-warn-and-return (format-message "`when' with empty body")
(list 'progn cond nil) '(empty-body when) t)))
(defmacro unless (cond &rest body)
"If COND yields nil, do BODY, else return nil.
When COND yields nil, eval BODY forms sequentially and return
value of last one, or nil if there are none."
(declare (indent 1) (debug t))
(if body
(cons 'if (cons cond (cons nil body)))
(macroexp-warn-and-return (format-message "`unless' with empty body")
(list 'progn cond nil) '(empty-body unless) t)))
(defsubst subr-primitive-p (object)
"Return t if OBJECT is a built-in primitive written in C.
Such objects can be functions or special forms."
(declare (side-effect-free error-free))
(and (subrp object)
(not (native-comp-function-p object))))
(defsubst primitive-function-p (object)
"Return t if OBJECT is a built-in primitive function.
This excludes special forms, since they are not functions."
(declare (side-effect-free error-free))
(and (subrp object)
(not (or (native-comp-function-p object)
(eq (cdr (subr-arity object)) 'unevalled)))))
(defsubst xor (cond1 cond2)
"Return the boolean exclusive-or of COND1 and COND2.
If only one of the arguments is non-nil, return it; otherwise
return nil."
(declare (pure t) (side-effect-free error-free))
(cond ((not cond1) cond2)
((not cond2) cond1)))
(defmacro dolist (spec &rest body)
"Loop over a list.
Evaluate BODY with VAR bound to each car from LIST, in turn.
Then evaluate RESULT to get return value, default nil.
\(fn (VAR LIST [RESULT]) BODY...)"
(declare (indent 1) (debug ((symbolp form &optional form) body)))
(unless (consp spec)
(signal 'wrong-type-argument (list 'consp spec)))
(unless (<= 2 (length spec) 3)
(signal 'wrong-number-of-arguments (list '(2 . 3) (length spec))))
(let ((tail (make-symbol "tail")))
`(let ((,tail ,(nth 1 spec)))
(while ,tail
(let ((,(car spec) (car ,tail)))
,@body
(setq ,tail (cdr ,tail))))
,@(cdr (cdr spec)))))
(defmacro dotimes (spec &rest body)
"Loop a certain number of times.
Evaluate BODY with VAR bound to successive integers running from 0,
inclusive, to COUNT, exclusive.
Finally RESULT is evaluated to get the return value (nil if
RESULT is omitted). Using RESULT is deprecated, and may result
in compilation warnings about unused variables.
\(fn (VAR COUNT [RESULT]) BODY...)"
(declare (indent 1) (debug dolist))
(let ((var (nth 0 spec))
(end (nth 1 spec))
(upper-bound (make-symbol "upper-bound"))
(counter (make-symbol "counter")))
`(let ((,upper-bound ,end)
(,counter 0))
(while (< ,counter ,upper-bound)
(let ((,var ,counter))
,@body)
(setq ,counter (1+ ,counter)))
,@(if (cddr spec)
;; FIXME: This let often leads to "unused var" warnings.
`((let ((,var ,counter)) ,@(cddr spec)))))))
(defmacro declare (&rest specs)
"Do not evaluate any arguments, and return nil.
If a `declare' form appears as the first form in the body of a
`defun' or `defmacro' form, SPECS specifies various additional
information about the function or macro; these go into effect
during the evaluation of the `defun' or `defmacro' form.
The possible values of SPECS are specified by
`defun-declarations-alist' and `macro-declarations-alist'.
For more information, see info node `(elisp)Declare Form'."
;; `declare' is handled directly by `defun/defmacro' rather than here.
;; If we get here, it's because there's a `declare' somewhere not attached
;; to a `defun/defmacro', i.e. a `declare' which doesn't do what it's
;; intended to do.
(let ((form `(declare . ,specs))) ;; FIXME: WIBNI we had &whole?
(macroexp-warn-and-return
(format-message "Stray `declare' form: %S" form)
;; Make a "unique" harmless form to circumvent
;; the cache in `macroexp-warn-and-return'.
`(progn ',form nil) nil 'compile-only)))
(defmacro ignore-errors (&rest body)
"Execute BODY; if an error occurs, return nil.
Otherwise, return result of last form in BODY.
See also `with-demoted-errors' that does something similar
without silencing all errors."
(declare (debug t) (indent 0))
`(condition-case nil (progn ,@body) (error nil)))
(defmacro ignore-error (condition &rest body)
"Execute BODY; if the error CONDITION occurs, return nil.
Otherwise, return result of last form in BODY.
CONDITION can also be a list of error conditions.
The CONDITION argument is not evaluated. Do not quote it."
(declare (debug t) (indent 1))
(cond
((and (eq (car-safe condition) 'quote)
(cdr condition) (null (cddr condition)))
(macroexp-warn-and-return
(format-message
"`ignore-error' condition argument should not be quoted: %S"
condition)
`(condition-case nil (progn ,@body) (,(cadr condition) nil))
nil t condition))
(body
`(condition-case nil (progn ,@body) (,condition nil)))
(t
(macroexp-warn-and-return (format-message "`ignore-error' with empty body")
nil '(empty-body ignore-error) t condition))))
;;;; Basic Lisp functions.
(defvar gensym-counter 0
"Number used to construct the name of the next symbol created by `gensym'.")
(defun gensym (&optional prefix)
"Return a new uninterned symbol.
The name is made by appending `gensym-counter' to PREFIX.
PREFIX is a string, and defaults to \"g\"."
(declare (important-return-value t))
(let ((num (prog1 gensym-counter
(setq gensym-counter (1+ gensym-counter)))))
(make-symbol (format "%s%d" (or prefix "g") num))))
(defun ignore (&rest _arguments)
"Ignore ARGUMENTS, do nothing, and return nil.
This function accepts any number of arguments in ARGUMENTS.
Also see `always'."
;; Not declared `side-effect-free' because we don't want calls to it
;; elided; see `byte-compile-ignore'.
(declare (ftype (function (&rest t) null))
(pure t) (completion ignore))
(interactive)
nil)
(defun always (&rest _arguments)
"Ignore ARGUMENTS, do nothing, and return t.
This function accepts any number of arguments in ARGUMENTS.
Also see `ignore'."
(declare (pure t) (side-effect-free error-free))
t)
(defun error (string &rest args)
"Signal an error, making a message by passing ARGS to `format-message'.
Errors cause entry to the debugger when `debug-on-error' is non-nil.
This can be overridden by `debug-ignored-errors'.
When `noninteractive' is non-nil (in particular, in batch mode), an
unhandled error calls `kill-emacs', which terminates the Emacs
session with a non-zero exit code.
To signal with MESSAGE without interpreting format characters
like `%', `\\=`' and `\\='', use (error \"%s\" MESSAGE).
In Emacs, the convention is that error messages start with a capital
letter but *do not* end with a period. Please follow this convention
for the sake of consistency.
To alter the look of the displayed error messages, you can use
the `command-error-function' variable."
(declare (ftype (function (string &rest t) nil)))
(signal 'error (list (apply #'format-message string args))))
(defun user-error (format &rest args)
"Signal a user error, making a message by passing ARGS to `format-message'.
This is like `error' except that a user error (or \"pilot error\") comes
from an incorrect manipulation by the user, not from an actual problem.
In contrast with other errors, user errors normally do not cause
entry to the debugger, even when `debug-on-error' is non-nil.
This can be overridden by `debug-ignored-errors'.
To signal with MESSAGE without interpreting format characters
like `%', `\\=`' and `\\='', use (user-error \"%s\" MESSAGE).
In Emacs, the convention is that error messages start with a capital
letter but *do not* end with a period. Please follow this convention
for the sake of consistency.
To alter the look of the displayed error messages, you can use
the `command-error-function' variable."
(signal 'user-error (list (apply #'format-message format args))))
(defun define-error (name message &optional parent)
"Define NAME as a new error signal.
MESSAGE is a string that will be output to the echo area if such an error
is signaled without being caught by a `condition-case'.
PARENT is either a signal or a list of signals from which it inherits.
Defaults to `error'."
(unless parent (setq parent 'error))
(let ((conditions
(if (consp parent)
(apply #'append
(mapcar (lambda (parent)
(cons parent
(or (get parent 'error-conditions)
(error "Unknown signal `%s'" parent))))
parent))
(cons parent (get parent 'error-conditions)))))
(put name 'error-conditions
(delete-dups (copy-sequence (cons name conditions))))
(when message (put name 'error-message message))))
;; We put this here instead of in frame.el so that it's defined even on
;; systems where frame.el isn't loaded.
(defun frame-configuration-p (object)
"Return non-nil if OBJECT seems to be a frame configuration.
Any list whose car is `frame-configuration' is assumed to be a frame
configuration."
(declare (pure t) (side-effect-free error-free))
(and (consp object)
(eq (car object) 'frame-configuration)))
(defun apply-partially (fun &rest args)
"Return a function that is a partial application of FUN to ARGS.
ARGS is a list of the first N arguments to pass to FUN.
The result is a new function which does the same as FUN, except that
the first N arguments are fixed at the values with which this function
was called."
(declare (side-effect-free error-free))
(lambda (&rest args2)
(apply fun (append args args2))))
(defun zerop (number)
"Return t if NUMBER is zero."
;; Used to be in C, but it's pointless since (= 0 n) is faster anyway because
;; = has a byte-code.
(declare (ftype (function (number) boolean))
(pure t) (side-effect-free t)
(compiler-macro (lambda (_) `(= 0 ,number))))
(= 0 number))
(defun fixnump (object)
"Return t if OBJECT is a fixnum."
(declare (ftype (function (t) boolean))
(side-effect-free error-free))
(and (integerp object)
(<= most-negative-fixnum object most-positive-fixnum)))
(defun bignump (object)
"Return t if OBJECT is a bignum."
(declare (ftype (function (t) boolean))
(side-effect-free error-free))
(and (integerp object) (not (fixnump object))))
(defun lsh (value count)
"Return VALUE with its bits shifted left by COUNT.
If COUNT is negative, shifting is actually to the right.
In this case, if VALUE is a negative fixnum treat it as unsigned,
i.e., subtract 2 * `most-negative-fixnum' from VALUE before shifting it.
Most uses of this function turn out to be mistakes. We recommend
to use `ash' instead, unless COUNT could ever be negative, and
if, when COUNT is negative, your program really needs the special
treatment of negative COUNT provided by this function."
(declare (ftype (function (integer integer) integer))
(compiler-macro
(lambda (form)
(macroexp-warn-and-return
(format-message "avoid `lsh'; use `ash' instead")
form '(suspicious lsh) t form)))
(side-effect-free t))
(when (and (< value 0) (< count 0))
(when (< value most-negative-fixnum)
(signal 'args-out-of-range (list value count)))
(setq value (logand (ash value -1) most-positive-fixnum))
(setq count (1+ count)))
(ash value count))
;;;; List functions.
;; Note: `internal--compiler-macro-cXXr' was copied from
;; `cl--compiler-macro-cXXr' in cl-macs.el. If you amend either one,
;; you may want to amend the other, too.
(defun internal--compiler-macro-cXXr (form x)
(let* ((head (car form))
(n (symbol-name head))
(i (- (length n) 2)))
(if (not (string-match "c[ad]+r\\'" n))
(if (and (fboundp head) (symbolp (symbol-function head)))
(internal--compiler-macro-cXXr
(cons (symbol-function head) (cdr form)) x)
(error "Compiler macro for cXXr applied to non-cXXr form"))
(while (> i (match-beginning 0))
(setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x))
(setq i (1- i)))
x)))
(defun caar (x)
"Return the car of the car of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car x)))
(defun cadr (x)
"Return the car of the cdr of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr x)))
(defun cdar (x)
"Return the cdr of the car of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car x)))
(defun cddr (x)
"Return the cdr of the cdr of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr x)))
(defun caaar (x)
"Return the `car' of the `car' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car (car x))))
(defun caadr (x)
"Return the `car' of the `car' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car (cdr x))))
(defun cadar (x)
"Return the `car' of the `cdr' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr (car x))))
(defun caddr (x)
"Return the `car' of the `cdr' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr (cdr x))))
(defun cdaar (x)
"Return the `cdr' of the `car' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car (car x))))
(defun cdadr (x)
"Return the `cdr' of the `car' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car (cdr x))))
(defun cddar (x)
"Return the `cdr' of the `cdr' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr (car x))))
(defun cdddr (x)
"Return the `cdr' of the `cdr' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr (cdr x))))
(defun caaaar (x)
"Return the `car' of the `car' of the `car' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car (car (car x)))))
(defun caaadr (x)
"Return the `car' of the `car' of the `car' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car (car (cdr x)))))
(defun caadar (x)
"Return the `car' of the `car' of the `cdr' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car (cdr (car x)))))
(defun caaddr (x)
"Return the `car' of the `car' of the `cdr' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (car (cdr (cdr x)))))
(defun cadaar (x)
"Return the `car' of the `cdr' of the `car' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr (car (car x)))))
(defun cadadr (x)
"Return the `car' of the `cdr' of the `car' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr (car (cdr x)))))
(defun caddar (x)
"Return the `car' of the `cdr' of the `cdr' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr (cdr (car x)))))
(defun cadddr (x)
"Return the `car' of the `cdr' of the `cdr' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(car (cdr (cdr (cdr x)))))
(defun cdaaar (x)
"Return the `cdr' of the `car' of the `car' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car (car (car x)))))
(defun cdaadr (x)
"Return the `cdr' of the `car' of the `car' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car (car (cdr x)))))
(defun cdadar (x)
"Return the `cdr' of the `car' of the `cdr' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car (cdr (car x)))))
(defun cdaddr (x)
"Return the `cdr' of the `car' of the `cdr' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (car (cdr (cdr x)))))
(defun cddaar (x)
"Return the `cdr' of the `cdr' of the `car' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr (car (car x)))))
(defun cddadr (x)
"Return the `cdr' of the `cdr' of the `car' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr (car (cdr x)))))
(defun cdddar (x)
"Return the `cdr' of the `cdr' of the `cdr' of the `car' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr (cdr (car x)))))
(defun cddddr (x)
"Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X."
(declare (compiler-macro internal--compiler-macro-cXXr))
(cdr (cdr (cdr (cdr x)))))
(defun last (list &optional n)
"Return the last link of LIST. Its car is the last element.
If LIST is nil, return nil.
If N is non-nil, return the Nth-to-last link of LIST.
If N is bigger than the length of LIST, return LIST."
(declare (ftype (function (list &optional integer) list))
(pure t) (side-effect-free t)) ; pure up to mutation
(if n
(and (>= n 0)
(let ((m (safe-length list)))
(if (< n m) (nthcdr (- m n) list) list)))
(and list
(nthcdr (1- (safe-length list)) list))))
(defun butlast (list &optional n)
"Return a copy of LIST with the last N elements removed.
If N is omitted or nil, return a copy of LIST without its last element.
If N is zero or negative, return LIST."
(declare (side-effect-free t))
(unless n
(setq n 1))
(if (<= n 0)
list
(take (- (length list) n) list)))
(defun nbutlast (list &optional n)
"Modify LIST to remove the last N elements.
If N is omitted or nil, remove the last element."
(let ((m (length list)))
(or n (setq n 1))
(and (< n m)
(progn
(if (> n 0) (setcdr (nthcdr (- (1- m) n) list) nil))
list))))
(defun delete-dups (list)
"Destructively remove `equal' duplicates from LIST.
Store the result in LIST and return it. LIST must be a proper list.
Of several `equal' occurrences of an element in LIST, the first
one is kept. See `seq-uniq' for non-destructive operation."
(let ((l (length list)))
(if (> l 100)
(let ((hash (make-hash-table :test #'equal :size l))
(tail list) retail)
(puthash (car list) t hash)
(while (setq retail (cdr tail))
(let ((elt (car retail)))
(if (gethash elt hash)
(setcdr tail (cdr retail))
(puthash elt t hash)
(setq tail retail)))))
(let ((tail list))
(while tail
(setcdr tail (delete (car tail) (cdr tail)))
(setq tail (cdr tail))))))
list)
;; See https://lists.gnu.org/r/emacs-devel/2013-05/msg00204.html
(defun delete-consecutive-dups (list &optional circular)
"Destructively remove `equal' consecutive duplicates from LIST.
First and last elements are considered consecutive if CIRCULAR is
non-nil.
Of several consecutive `equal' occurrences, the one earliest in
the list is kept."
(let ((tail list) last)
(while (cdr tail)
(if (equal (car tail) (cadr tail))
(setcdr tail (cddr tail))
(setq last tail
tail (cdr tail))))
(if (and circular
last
(equal (car tail) (car list)))
(setcdr last nil)))
list)
(defun number-sequence (from &optional to inc)
"Return a sequence of numbers from FROM to TO (both inclusive) as a list.
INC is the increment used between numbers in the sequence and defaults to 1.
So, the Nth element of the list is (+ FROM (* N INC)) where N counts from
zero. TO is included only if there is an N for which TO = FROM + N * INC.
If TO is nil or numerically equal to FROM, return (FROM).
If INC is positive and TO is less than FROM, or INC is negative
and TO is larger than FROM, return nil.
If INC is zero and TO is neither nil nor numerically equal to
FROM, signal an error.
This function is primarily designed for integer arguments.
Nevertheless, FROM, TO and INC can be integer or float. However,
floating point arithmetic is inexact. For instance, depending on
the machine, it may quite well happen that
\(number-sequence 0.4 0.6 0.2) returns the one element list (0.4),
whereas (number-sequence 0.4 0.8 0.2) returns a list with three
elements. Thus, if some of the arguments are floats and one wants
to make sure that TO is included, one may have to explicitly write
TO as (+ FROM (* N INC)) or use a variable whose value was
computed with this exact expression. Alternatively, you can,
of course, also replace TO with a slightly larger value
\(or a slightly more negative value if INC is negative)."
(declare (side-effect-free t))
(if (or (not to) (= from to))
(list from)
(or inc (setq inc 1))
(when (zerop inc) (error "The increment can not be zero"))
(let (seq (n 0) (next from))
(if (> inc 0)
(while (<= next to)
(setq seq (cons next seq)
n (1+ n)
next (+ from (* n inc))))
(while (>= next to)
(setq seq (cons next seq)
n (1+ n)
next (+ from (* n inc)))))
(nreverse seq))))
(defun copy-tree (tree &optional vectors-and-records)
"Make a copy of TREE.
If TREE is a cons cell, this recursively copies both its car and its cdr.
Contrast to `copy-sequence', which copies only along the cdrs.
With the second argument VECTORS-AND-RECORDS non-nil, this
traverses and copies vectors and records as well as conses."
(declare (side-effect-free error-free))
(if (consp tree)
(let (result)
(while (consp tree)
(let ((newcar (car tree)))
(if (or (consp (car tree))
(and vectors-and-records
(or (vectorp (car tree)) (recordp (car tree)))))
(setq newcar (copy-tree (car tree) vectors-and-records)))
(push newcar result))
(setq tree (cdr tree)))
(nconc (nreverse result)
(if (and vectors-and-records (or (vectorp tree) (recordp tree)))
(copy-tree tree vectors-and-records)
tree)))
(if (and vectors-and-records (or (vectorp tree) (recordp tree)))
(let ((i (length (setq tree (copy-sequence tree)))))
(while (>= (setq i (1- i)) 0)
(aset tree i (copy-tree (aref tree i) vectors-and-records)))
tree)
tree)))
;;;; Various list-search functions.
(defun assoc-default (key alist &optional test default)
"Find object KEY in a pseudo-alist ALIST.
ALIST is a list of conses or objects. Each element
(or the element's car, if it is a cons) is compared with KEY by
calling TEST, with two arguments: (i) the element or its car,
and (ii) KEY.
If that is non-nil, the element matches; then `assoc-default'
returns the element's cdr, if it is a cons, or DEFAULT if the
element is not a cons.
If no element matches, the value is nil.
If TEST is omitted or nil, `equal' is used."
(declare (important-return-value t))
(let (found (tail alist) value)
(while (and tail (not found))
(let ((elt (car tail)))
(when (funcall (or test #'equal) (if (consp elt) (car elt) elt) key)
(setq found t value (if (consp elt) (cdr elt) default))))
(setq tail (cdr tail)))
value))
(defun member-ignore-case (elt list)
"Like `member', but ignore differences in case and text representation.
ELT must be a string. Upper-case and lower-case letters are treated as equal.
Unibyte strings are converted to multibyte for comparison.
Non-strings in LIST are ignored."
(declare (side-effect-free t))
(while (and list
(not (and (stringp (car list))
(string-equal-ignore-case elt (car list)))))
(setq list (cdr list)))
list)
(defun assoc-delete-all (key alist &optional test)
"Delete from ALIST all elements whose car is KEY.
Compare keys with TEST. Defaults to `equal'.
Return the modified alist.
Elements of ALIST that are not conses are ignored."
(declare (important-return-value t))
(unless test (setq test #'equal))
(while (and (consp (car alist))
(funcall test (caar alist) key))
(setq alist (cdr alist)))
(let ((tail alist) tail-cdr)
(while (setq tail-cdr (cdr tail))
(if (and (consp (car tail-cdr))
(funcall test (caar tail-cdr) key))
(setcdr tail (cdr tail-cdr))
(setq tail tail-cdr))))
alist)
(defun assq-delete-all (key alist)
"Delete from ALIST all elements whose car is `eq' to KEY.
Return the modified alist.
Elements of ALIST that are not conses are ignored."
(declare (important-return-value t))
(assoc-delete-all key alist #'eq))
(defun rassq-delete-all (value alist)
"Delete from ALIST all elements whose cdr is `eq' to VALUE.
Return the modified alist.
Elements of ALIST that are not conses are ignored."
(declare (important-return-value t))
(while (and (consp (car alist))
(eq (cdr (car alist)) value))
(setq alist (cdr alist)))
(let ((tail alist) tail-cdr)
(while (setq tail-cdr (cdr tail))
(if (and (consp (car tail-cdr))
(eq (cdr (car tail-cdr)) value))
(setcdr tail (cdr tail-cdr))
(setq tail tail-cdr))))
alist)
(defun alist-get (key alist &optional default remove testfn)
"Find the first element of ALIST whose `car' equals KEY and return its `cdr'.
If KEY is not found in ALIST, return DEFAULT.
Equality with KEY is tested by TESTFN, defaulting to `eq'.
You can use `alist-get' in \"place expressions\"; i.e., as a
generalized variable. Doing this will modify an existing
association (more precisely, the first one if multiple exist), or
add a new element to the beginning of ALIST, destructively
modifying the list stored in ALIST.
Example:
(setq foo \\='((a . 0)))
(setf (alist-get \\='a foo) 1
(alist-get \\='b foo) 2)
foo => ((b . 2) (a . 1))
When using it to set a value, optional argument REMOVE non-nil
means to remove KEY from ALIST if the new value is `eql' to
DEFAULT (more precisely the first found association will be
deleted from the alist).
Example:
(setq foo \\='((a . 1) (b . 2)))
(setf (alist-get \\='b foo nil \\='remove) nil)