mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-25 07:28:20 +00:00
* doc/lispref/variables.texi (Scope): Mention the availability of lexbind.
(Lexical Binding): New node. * doc/lispref/eval.texi (Eval): Add `eval's new `lexical' arg. * lisp/emacs-lisp/cconv.el (cconv-liftwhen): Increase threshold. (cconv-closure-convert-rec): Convert interactive spec in empty lexenv. (cconv-analyse-use): Improve unused vars warnings. (cconv-analyse-form): Analyze interactive spec in empty lexenv. * lisp/emacs-lisp/bytecomp.el (byte-compile-lambda): Always byte-compile the interactive spec in lexical-binding mode. (byte-compile-refresh-preloaded): Don't reload byte-compiler files. * lisp/custom.el (custom-initialize-default): Use defvar. (custom-declare-variable): Set the special-variable-p flag. * lisp/help-fns.el (help-make-usage): Drop leading underscores. * lisp/dired.el (dired-revert, dired-make-relative): Mark unused args. (dired-unmark-all-files): Remove unused var `query'. (dired-overwrite-confirmed): Declare. (dired-restore-desktop-buffer): Don't use dynamically scoped arg names. * lisp/mpc.el: Mark unused args. (mpc--faster-toggle): Remove unused var `songnb'. * lisp/server.el (server-kill-buffer-running): Move before first use. * lisp/minibuffer.el: Mark unused args. * src/callint.c (quotify_arg): Simplify the logic. (Fcall_interactively): Use lexical binding when evaluating the interactive spec of a lexically bound function.
This commit is contained in:
parent
39605a343b
commit
d032d5e7df
4
aclocal.m4
vendored
4
aclocal.m4
vendored
@ -13,8 +13,8 @@
|
||||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
|
||||
[m4_warning([this file was generated for autoconf 2.67.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
|
||||
[m4_warning([this file was generated for autoconf 2.68.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically `autoreconf'.])])
|
||||
|
@ -1,3 +1,9 @@
|
||||
2011-03-01 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* variables.texi (Scope): Mention the availability of lexical scoping.
|
||||
(Lexical Binding): New node.
|
||||
* eval.texi (Eval): Add `eval's new `lexical' arg.
|
||||
|
||||
2011-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* vol2.texi (Top):
|
||||
|
@ -466,7 +466,8 @@ Functions
|
||||
* Declaring Functions:: Telling the compiler that a function is defined.
|
||||
* Function Safety:: Determining whether a function is safe to call.
|
||||
* Related Topics:: Cross-references to specific Lisp primitives
|
||||
that have a special bearing on how functions work.
|
||||
that have a special bearing on how
|
||||
functions work.
|
||||
|
||||
Lambda Expressions
|
||||
|
||||
|
@ -585,6 +585,11 @@ occurrence in a program being run. On rare occasions, you may need to
|
||||
write code that evaluates a form that is computed at run time, such as
|
||||
after reading a form from text being edited or getting one from a
|
||||
property list. On these occasions, use the @code{eval} function.
|
||||
Often @code{eval} is not needed and something else should be used instead.
|
||||
For example, to get the value of a variable, while @code{eval} works,
|
||||
@code{symbol-value} is preferable; or rather than store expressions
|
||||
in a property list that then need to go through @code{eval}, it is better to
|
||||
store functions instead that are then passed to @code{funcall}.
|
||||
|
||||
The functions and variables described in this section evaluate forms,
|
||||
specify limits to the evaluation process, or record recently returned
|
||||
@ -596,10 +601,13 @@ to store an expression in the data structure and evaluate it. Using
|
||||
functions provides the ability to pass information to them as
|
||||
arguments.
|
||||
|
||||
@defun eval form
|
||||
@defun eval form &optional lexical
|
||||
This is the basic function evaluating an expression. It evaluates
|
||||
@var{form} in the current environment and returns the result. How the
|
||||
evaluation proceeds depends on the type of the object (@pxref{Forms}).
|
||||
@var{lexical} if non-nil means to evaluate @var{form} using lexical scoping
|
||||
rules (@pxref{Lexical Binding}) instead of the default dynamic scoping used
|
||||
historically in Emacs Lisp.
|
||||
|
||||
Since @code{eval} is a function, the argument expression that appears
|
||||
in a call to @code{eval} is evaluated twice: once as preparation before
|
||||
|
@ -25,22 +25,22 @@ textual Lisp program is written using the read syntax for the symbol
|
||||
representing the variable.
|
||||
|
||||
@menu
|
||||
* Global Variables:: Variable values that exist permanently, everywhere.
|
||||
* Constant Variables:: Certain "variables" have values that never change.
|
||||
* Local Variables:: Variable values that exist only temporarily.
|
||||
* Void Variables:: Symbols that lack values.
|
||||
* Defining Variables:: A definition says a symbol is used as a variable.
|
||||
* Tips for Defining:: Things you should think about when you
|
||||
* Global Variables:: Variable values that exist permanently, everywhere.
|
||||
* Constant Variables:: Certain "variables" have values that never change.
|
||||
* Local Variables:: Variable values that exist only temporarily.
|
||||
* Void Variables:: Symbols that lack values.
|
||||
* Defining Variables:: A definition says a symbol is used as a variable.
|
||||
* Tips for Defining:: Things you should think about when you
|
||||
define a variable.
|
||||
* Accessing Variables:: Examining values of variables whose names
|
||||
* Accessing Variables:: Examining values of variables whose names
|
||||
are known only at run time.
|
||||
* Setting Variables:: Storing new values in variables.
|
||||
* Variable Scoping:: How Lisp chooses among local and global values.
|
||||
* Buffer-Local Variables:: Variable values in effect only in one buffer.
|
||||
* File Local Variables:: Handling local variable lists in files.
|
||||
* Directory Local Variables:: Local variables common to all files in a directory.
|
||||
* Frame-Local Variables:: Frame-local bindings for variables.
|
||||
* Variable Aliases:: Variables that are aliases for other variables.
|
||||
* Setting Variables:: Storing new values in variables.
|
||||
* Variable Scoping:: How Lisp chooses among local and global values.
|
||||
* Buffer-Local Variables:: Variable values in effect only in one buffer.
|
||||
* File Local Variables:: Handling local variable lists in files.
|
||||
* Directory Local Variables:: Local variables common to all files in a directory.
|
||||
* Frame-Local Variables:: Frame-local bindings for variables.
|
||||
* Variable Aliases:: Variables that are aliases for other variables.
|
||||
* Variables with Restricted Values:: Non-constant variables whose value can
|
||||
@emph{not} be an arbitrary Lisp object.
|
||||
@end menu
|
||||
@ -437,14 +437,18 @@ this reason, user options must be defined with @code{defvar}.
|
||||
This special form defines @var{symbol} as a variable and can also
|
||||
initialize and document it. The definition informs a person reading
|
||||
your code that @var{symbol} is used as a variable that might be set or
|
||||
changed. Note that @var{symbol} is not evaluated; the symbol to be
|
||||
defined must appear explicitly in the @code{defvar}.
|
||||
changed. It also declares this variable as @dfn{special}, meaning that it
|
||||
should always use dynamic scoping rules. Note that @var{symbol} is not
|
||||
evaluated; the symbol to be defined must appear explicitly in the
|
||||
@code{defvar}.
|
||||
|
||||
If @var{symbol} is void and @var{value} is specified, @code{defvar}
|
||||
evaluates it and sets @var{symbol} to the result. But if @var{symbol}
|
||||
already has a value (i.e., it is not void), @var{value} is not even
|
||||
evaluated, and @var{symbol}'s value remains unchanged. If @var{value}
|
||||
is omitted, the value of @var{symbol} is not changed in any case.
|
||||
evaluated, and @var{symbol}'s value remains unchanged.
|
||||
If @var{value} is omitted, the value of @var{symbol} is not changed in any
|
||||
case; instead, the only effect of @code{defvar} is to declare locally that this
|
||||
variable exists elsewhere and should hence always use dynamic scoping rules.
|
||||
|
||||
If @var{symbol} has a buffer-local binding in the current buffer,
|
||||
@code{defvar} operates on the default value, which is buffer-independent,
|
||||
@ -881,7 +885,7 @@ the others.
|
||||
@cindex extent
|
||||
@cindex dynamic scoping
|
||||
@cindex lexical scoping
|
||||
Local bindings in Emacs Lisp have @dfn{indefinite scope} and
|
||||
By default, local bindings in Emacs Lisp have @dfn{indefinite scope} and
|
||||
@dfn{dynamic extent}. @dfn{Scope} refers to @emph{where} textually in
|
||||
the source code the binding can be accessed. ``Indefinite scope'' means
|
||||
that any part of the program can potentially access the variable
|
||||
@ -893,6 +897,8 @@ lasts as long as the activation of the construct that established it.
|
||||
@dfn{dynamic scoping}. By contrast, most programming languages use
|
||||
@dfn{lexical scoping}, in which references to a local variable must be
|
||||
located textually within the function or block that binds the variable.
|
||||
Emacs can also support lexical scoping, upon request (@pxref{Lexical
|
||||
Binding}).
|
||||
|
||||
@cindex CL note---special variables
|
||||
@quotation
|
||||
@ -901,11 +907,12 @@ dynamically scoped, like all variables in Emacs Lisp.
|
||||
@end quotation
|
||||
|
||||
@menu
|
||||
* Scope:: Scope means where in the program a value is visible.
|
||||
* Scope:: Scope means where in the program a value is visible.
|
||||
Comparison with other languages.
|
||||
* Extent:: Extent means how long in time a value exists.
|
||||
* Impl of Scope:: Two ways to implement dynamic scoping.
|
||||
* Using Scoping:: How to use dynamic scoping carefully and avoid problems.
|
||||
* Extent:: Extent means how long in time a value exists.
|
||||
* Impl of Scope:: Two ways to implement dynamic scoping.
|
||||
* Using Scoping:: How to use dynamic scoping carefully and avoid problems.
|
||||
* Lexical Binding::
|
||||
@end menu
|
||||
|
||||
@node Scope
|
||||
@ -969,12 +976,12 @@ Here, when @code{foo} is called by @code{binder}, it binds @code{x}.
|
||||
by @code{foo} instead of the one bound by @code{binder}.
|
||||
@end itemize
|
||||
|
||||
Emacs Lisp uses dynamic scoping because simple implementations of
|
||||
Emacs Lisp used dynamic scoping by default because simple implementations of
|
||||
lexical scoping are slow. In addition, every Lisp system needs to offer
|
||||
dynamic scoping at least as an option; if lexical scoping is the norm,
|
||||
there must be a way to specify dynamic scoping instead for a particular
|
||||
variable. It might not be a bad thing for Emacs to offer both, but
|
||||
implementing it with dynamic scoping only was much easier.
|
||||
dynamic scoping at least as an option; if lexical scoping is the norm, there
|
||||
must be a way to specify dynamic scoping instead for a particular variable.
|
||||
Nowadays, Emacs offers both, but the default is still to use exclusively
|
||||
dynamic scoping.
|
||||
|
||||
@node Extent
|
||||
@subsection Extent
|
||||
@ -1088,6 +1095,48 @@ for inter-function usage. It also avoids a warning from the byte
|
||||
compiler. Choose the variable's name to avoid name conflicts---don't
|
||||
use short names like @code{x}.
|
||||
|
||||
|
||||
@node Lexical Binding
|
||||
@subsection Use of Lexical Scoping
|
||||
|
||||
Emacs Lisp can be evaluated in two different modes: in dynamic binding mode or
|
||||
lexical binding mode. In dynamic binding mode, all local variables use dynamic
|
||||
scoping, whereas in lexical binding mode variables that have been declared
|
||||
@dfn{special} (i.e., declared with @code{defvar} or @code{defconst}) use
|
||||
dynamic scoping and all others use lexical scoping.
|
||||
|
||||
@defvar lexical-binding
|
||||
When non-nil, evaluation of Lisp code uses lexical scoping for non-special
|
||||
local variables instead of dynamic scoping. If nil, dynamic scoping is used
|
||||
for all local variables. This variable is typically set for a whole Elisp file
|
||||
via file local variables (@pxref{File Local Variables}).
|
||||
@end defvar
|
||||
|
||||
@defun special-variable-p SYMBOL
|
||||
Return whether SYMBOL has been declared as a special variable, via
|
||||
@code{defvar} or @code{defconst}.
|
||||
@end defun
|
||||
|
||||
The use of a special variable as a formal argument in a function is generally
|
||||
discouraged and its behavior in lexical binding mode is unspecified (it may use
|
||||
lexical scoping sometimes and dynamic scoping other times).
|
||||
|
||||
Functions like @code{symbol-value}, @code{boundp}, or @code{set} only know
|
||||
about dynamically scoped variables, so you cannot get the value of a lexical
|
||||
variable via @code{symbol-value} and neither can you change it via @code{set}.
|
||||
Another particularity is that code in the body of a @code{defun} or
|
||||
@code{defmacro} cannot refer to surrounding lexical variables.
|
||||
|
||||
Evaluation of a @code{lambda} expression in lexical binding mode will not just
|
||||
return that lambda expression unchanged, as in the dynamic binding case, but
|
||||
will instead construct a new object that remembers the current lexical
|
||||
environment in which that lambda expression was defined, so that the function
|
||||
body can later be evaluated in the proper context. Those objects are called
|
||||
@dfn{closures}. They are also functions, in the sense that they are accepted
|
||||
by @code{funcall}, and they are represented by a cons cell whose @code{car} is
|
||||
the symbol @code{closure}.
|
||||
|
||||
|
||||
@node Buffer-Local Variables
|
||||
@section Buffer-Local Variables
|
||||
@cindex variable, buffer-local
|
||||
@ -1103,9 +1152,9 @@ local to each terminal, or to each frame. @xref{Multiple Terminals},
|
||||
and @xref{Frame-Local Variables}.)
|
||||
|
||||
@menu
|
||||
* Intro to Buffer-Local:: Introduction and concepts.
|
||||
* Creating Buffer-Local:: Creating and destroying buffer-local bindings.
|
||||
* Default Value:: The default value is seen in buffers
|
||||
* Intro to Buffer-Local:: Introduction and concepts.
|
||||
* Creating Buffer-Local:: Creating and destroying buffer-local bindings.
|
||||
* Default Value:: The default value is seen in buffers
|
||||
that don't have their own buffer-local values.
|
||||
@end menu
|
||||
|
||||
|
@ -1,3 +1,24 @@
|
||||
2011-03-01 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/cconv.el (cconv-liftwhen): Increase threshold.
|
||||
(cconv-closure-convert-rec): Convert interactive spec in empty lexenv.
|
||||
(cconv-analyse-use): Improve unused vars warnings.
|
||||
(cconv-analyse-form): Analyze interactive spec in empty lexenv.
|
||||
* emacs-lisp/bytecomp.el (byte-compile-lambda): Always byte-compile
|
||||
the interactive spec in lexical-binding mode.
|
||||
(byte-compile-refresh-preloaded): Don't reload byte-compiler files.
|
||||
* custom.el (custom-initialize-default): Use defvar.
|
||||
(custom-declare-variable): Set the special-variable-p flag.
|
||||
* help-fns.el (help-make-usage): Drop leading underscores.
|
||||
* dired.el (dired-revert, dired-make-relative): Mark unused args.
|
||||
(dired-unmark-all-files): Remove unused var `query'.
|
||||
(dired-overwrite-confirmed): Declare.
|
||||
(dired-restore-desktop-buffer): Don't use dynamically scoped arg names.
|
||||
* mpc.el: Mark unused args.
|
||||
(mpc--faster-toggle): Remove unused var `songnb'.
|
||||
* server.el (server-kill-buffer-running): Move before first use.
|
||||
* minibuffer.el: Mark unused args.
|
||||
|
||||
2011-02-26 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/cconv.el (cconv-closure-convert-rec): Fix last change for
|
||||
@ -335,6 +356,15 @@
|
||||
|
||||
Merge funvec patch.
|
||||
|
||||
2004-05-20 Miles Bader <miles@gnu.org>
|
||||
|
||||
* subr.el (functionp): Use `funvecp' instead of
|
||||
`byte-compiled-function-p'.
|
||||
* help-fns.el (describe-function-1): Describe curried functions
|
||||
and other funvecs as such.
|
||||
(help-highlight-arguments): Only format things that look like a
|
||||
function.
|
||||
|
||||
2004-04-29 Miles Bader <miles@gnu.org>
|
||||
|
||||
* emacs-lisp/bytecomp.el (byte-compile-top-level): Add new entries
|
||||
|
@ -1,10 +0,0 @@
|
||||
2004-05-20 Miles Bader <miles@gnu.org>
|
||||
|
||||
* subr.el (functionp): Use `funvecp' instead of
|
||||
`byte-compiled-function-p'.
|
||||
* help-fns.el (describe-function-1): Describe curried functions
|
||||
and other funvecs as such.
|
||||
(help-highlight-arguments): Only format things that look like a
|
||||
function.
|
||||
|
||||
;; arch-tag: 87f75aac-de53-40d7-96c7-3befaa771cb1
|
@ -222,6 +222,9 @@ compile-onefile:
|
||||
# cannot have prerequisites.
|
||||
.el.elc:
|
||||
@echo Compiling $<
|
||||
@# The BIG_STACK_OPTS are only needed to byte-compile the byte-compiler
|
||||
@# files, which is normally done in compile-first, but may also be
|
||||
@# recompiled via this rule.
|
||||
@$(emacs) $(BIG_STACK_OPTS) $(BYTE_COMPILE_EXTRA_FLAGS) \
|
||||
-f batch-byte-compile $<
|
||||
|
||||
|
@ -55,11 +55,9 @@ Otherwise, if symbol has a `saved-value' property, it will evaluate
|
||||
the car of that and use it as the default binding for symbol.
|
||||
Otherwise, VALUE will be evaluated and used as the default binding for
|
||||
symbol."
|
||||
(unless (default-boundp symbol)
|
||||
;; Use the saved value if it exists, otherwise the standard setting.
|
||||
(set-default symbol (eval (if (get symbol 'saved-value)
|
||||
(car (get symbol 'saved-value))
|
||||
value)))))
|
||||
(eval `(defvar ,symbol ,(if (get symbol 'saved-value)
|
||||
(car (get symbol 'saved-value))
|
||||
value))))
|
||||
|
||||
(defun custom-initialize-set (symbol value)
|
||||
"Initialize SYMBOL based on VALUE.
|
||||
@ -81,15 +79,15 @@ The value is either the symbol's current value
|
||||
\(as obtained using the `:get' function), if any,
|
||||
or the value in the symbol's `saved-value' property if any,
|
||||
or (last of all) VALUE."
|
||||
(funcall (or (get symbol 'custom-set) 'set-default)
|
||||
symbol
|
||||
(cond ((default-boundp symbol)
|
||||
(funcall (or (get symbol 'custom-get) 'default-value)
|
||||
symbol))
|
||||
((get symbol 'saved-value)
|
||||
(eval (car (get symbol 'saved-value))))
|
||||
(t
|
||||
(eval value)))))
|
||||
(funcall (or (get symbol 'custom-set) 'set-default)
|
||||
symbol
|
||||
(cond ((default-boundp symbol)
|
||||
(funcall (or (get symbol 'custom-get) 'default-value)
|
||||
symbol))
|
||||
((get symbol 'saved-value)
|
||||
(eval (car (get symbol 'saved-value))))
|
||||
(t
|
||||
(eval value)))))
|
||||
|
||||
(defun custom-initialize-changed (symbol value)
|
||||
"Initialize SYMBOL with VALUE.
|
||||
@ -142,10 +140,8 @@ set to nil, as the value is no longer rogue."
|
||||
;; Maybe this option was rogue in an earlier version. It no longer is.
|
||||
(when (get symbol 'force-value)
|
||||
(put symbol 'force-value nil))
|
||||
(when doc
|
||||
(if (keywordp doc)
|
||||
(error "Doc string is missing")
|
||||
(put symbol 'variable-documentation doc)))
|
||||
(if (keywordp doc)
|
||||
(error "Doc string is missing"))
|
||||
(let ((initialize 'custom-initialize-reset)
|
||||
(requests nil))
|
||||
(unless (memq :group args)
|
||||
@ -189,6 +185,13 @@ set to nil, as the value is no longer rogue."
|
||||
;; Do the actual initialization.
|
||||
(unless custom-dont-initialize
|
||||
(funcall initialize symbol default)))
|
||||
;; Use defvar to set the docstring as well as the special-variable-p flag.
|
||||
;; FIXME: We should reproduce more of `defvar's behavior, such as the warning
|
||||
;; when the var is currently let-bound.
|
||||
(if (not (default-boundp symbol))
|
||||
;; Don't use defvar to avoid setting a default-value when undesired.
|
||||
(when doc (put symbol 'variable-documentation doc))
|
||||
(eval `(defvar ,symbol nil ,@(when doc (list doc)))))
|
||||
(push symbol current-load-list)
|
||||
(run-hooks 'custom-define-hook)
|
||||
symbol)
|
||||
|
@ -1168,7 +1168,7 @@ If HDR is non-nil, insert a header line with the directory name."
|
||||
|
||||
;; Reverting a dired buffer
|
||||
|
||||
(defun dired-revert (&optional arg noconfirm)
|
||||
(defun dired-revert (&optional _arg _noconfirm)
|
||||
"Reread the dired buffer.
|
||||
Must also be called after `dired-actual-switches' have changed.
|
||||
Should not fail even on completely garbaged buffers.
|
||||
@ -2129,7 +2129,7 @@ Optional arg GLOBAL means to replace all matches."
|
||||
;; dired-get-filename.
|
||||
(concat (or dir default-directory) file))
|
||||
|
||||
(defun dired-make-relative (file &optional dir ignore)
|
||||
(defun dired-make-relative (file &optional dir _ignore)
|
||||
"Convert FILE (an absolute file name) to a name relative to DIR.
|
||||
If this is impossible, return FILE unchanged.
|
||||
DIR must be a directory name, not a file name."
|
||||
@ -3219,7 +3219,7 @@ Type \\[help-command] at that time for help."
|
||||
(interactive "cRemove marks (RET means all): \nP")
|
||||
(save-excursion
|
||||
(let* ((count 0)
|
||||
(inhibit-read-only t) case-fold-search query
|
||||
(inhibit-read-only t) case-fold-search
|
||||
(string (format "\n%c" mark))
|
||||
(help-form "\
|
||||
Type SPC or `y' to unmark one file, DEL or `n' to skip to next,
|
||||
@ -3494,6 +3494,8 @@ Anything else means ask for each directory."
|
||||
(declare-function dnd-get-local-file-name "dnd" (uri &optional must-exist))
|
||||
(declare-function dnd-get-local-file-uri "dnd" (uri))
|
||||
|
||||
(defvar dired-overwrite-confirmed) ;Defined in dired-aux.
|
||||
|
||||
(defun dired-dnd-handle-local-file (uri action)
|
||||
"Copy, move or link a file to the dired directory.
|
||||
URI is the file to handle, ACTION is one of copy, move, link or ask.
|
||||
@ -3572,21 +3574,21 @@ Ask means pop up a menu for the user to select one of copy, move or link."
|
||||
(function (lambda (f) (desktop-file-name (car f) dirname)))
|
||||
dired-subdir-alist)))))
|
||||
|
||||
(defun dired-restore-desktop-buffer (desktop-buffer-file-name
|
||||
desktop-buffer-name
|
||||
desktop-buffer-misc)
|
||||
(defun dired-restore-desktop-buffer (_file-name
|
||||
_buffer-name
|
||||
misc-data)
|
||||
"Restore a dired buffer specified in a desktop file."
|
||||
;; First element of `desktop-buffer-misc' is the value of `dired-directory'.
|
||||
;; First element of `misc-data' is the value of `dired-directory'.
|
||||
;; This value is a directory name, optionally with shell wildcard or
|
||||
;; a directory name followed by list of files.
|
||||
(let* ((dired-dir (car desktop-buffer-misc))
|
||||
(let* ((dired-dir (car misc-data))
|
||||
(dir (if (consp dired-dir) (car dired-dir) dired-dir)))
|
||||
(if (file-directory-p (file-name-directory dir))
|
||||
(progn
|
||||
(dired dired-dir)
|
||||
;; The following elements of `desktop-buffer-misc' are the keys
|
||||
;; The following elements of `misc-data' are the keys
|
||||
;; from `dired-subdir-alist'.
|
||||
(mapc 'dired-maybe-insert-subdir (cdr desktop-buffer-misc))
|
||||
(mapc 'dired-maybe-insert-subdir (cdr misc-data))
|
||||
(current-buffer))
|
||||
(message "Desktop: Directory %s no longer exists." dir)
|
||||
(when desktop-missing-file-warning (sit-for 1))
|
||||
|
@ -308,6 +308,10 @@
|
||||
|
||||
;; ((lambda ...) ...)
|
||||
(defun byte-compile-unfold-lambda (form &optional name)
|
||||
;; In lexical-binding mode, let and functions don't bind vars in the same way
|
||||
;; (let obey special-variable-p, but functions don't). This doesn't matter
|
||||
;; here, because function's behavior is underspecified so it can safely be
|
||||
;; turned into a `let', even though the reverse is not true.
|
||||
(or name (setq name "anonymous lambda"))
|
||||
(let ((lambda (car form))
|
||||
(values (cdr form)))
|
||||
|
@ -2563,6 +2563,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||
;; b-c-lambda didn't produce a compiled-function, so it's either a trivial
|
||||
;; function, or this is Emacs 18, or generate-emacs19-bytecodes is off.
|
||||
((let (tmp)
|
||||
;; FIXME: can this happen?
|
||||
(if (and (setq tmp (assq 'byte-code (cdr-safe (cdr fun))))
|
||||
(null (cdr (memq tmp fun))))
|
||||
;; Generate a make-byte-code call.
|
||||
@ -2587,7 +2588,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||
(list 'quote fun))))))
|
||||
|
||||
;; Turn a function into an ordinary lambda. Needed for v18 files.
|
||||
(defun byte-compile-byte-code-unmake (function)
|
||||
(defun byte-compile-byte-code-unmake (function) ;FIXME: what is it?
|
||||
(if (consp function)
|
||||
function;;It already is a lambda.
|
||||
(setq function (append function nil)) ; turn it into a list
|
||||
@ -2685,16 +2686,19 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||
;; compile it, because `call-interactively' looks at the
|
||||
;; args of `list'. Actually, compile it to get warnings,
|
||||
;; but don't use the result.
|
||||
(let ((form (nth 1 bytecomp-int)))
|
||||
(let* ((form (nth 1 bytecomp-int))
|
||||
(newform (byte-compile-top-level form)))
|
||||
(while (memq (car-safe form) '(let let* progn save-excursion))
|
||||
(while (consp (cdr form))
|
||||
(setq form (cdr form)))
|
||||
(setq form (car form)))
|
||||
(if (eq (car-safe form) 'list)
|
||||
(byte-compile-top-level (nth 1 bytecomp-int))
|
||||
(setq bytecomp-int (list 'interactive
|
||||
(byte-compile-top-level
|
||||
(nth 1 bytecomp-int)))))))
|
||||
(if (and (eq (car-safe form) 'list)
|
||||
;; The spec is evaled in callint.c in dynamic-scoping
|
||||
;; mode, so just leaving the form unchanged would mean
|
||||
;; it won't be eval'd in the right mode.
|
||||
(not lexical-binding))
|
||||
nil
|
||||
(setq bytecomp-int `(interactive ,newform)))))
|
||||
((cdr bytecomp-int)
|
||||
(byte-compile-warn "malformed interactive spec: %s"
|
||||
(prin1-to-string bytecomp-int)))))
|
||||
@ -3826,7 +3830,6 @@ Return the offset in the form (VAR . OFFSET)."
|
||||
(byte-compile-push-constant nil)))))
|
||||
|
||||
(defun byte-compile-not-lexical-var-p (var)
|
||||
;; FIXME: this doesn't catch defcustoms!
|
||||
(or (not (symbolp var))
|
||||
(special-variable-p var)
|
||||
(memq var byte-compile-bound-variables)
|
||||
@ -4560,7 +4563,14 @@ Use with caution."
|
||||
(setq f (car f))
|
||||
(if (string-match "elc\\'" f) (setq f (substring f 0 -1)))
|
||||
(when (and (file-readable-p f)
|
||||
(file-newer-than-file-p f emacs-file))
|
||||
(file-newer-than-file-p f emacs-file)
|
||||
;; Don't reload the source version of the files below
|
||||
;; because that causes subsequent byte-compilation to
|
||||
;; be a lot slower and need a higher max-lisp-eval-depth,
|
||||
;; so it can cause recompilation to fail.
|
||||
(not (member (file-name-nondirectory f)
|
||||
'("pcase.el" "bytecomp.el" "macroexp.el"
|
||||
"cconv.el" "byte-opt.el"))))
|
||||
(message "Reloading stale %s" (file-name-nondirectory f))
|
||||
(condition-case nil
|
||||
(load f 'noerror nil 'nosuffix)
|
||||
|
@ -65,21 +65,54 @@
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
;;; TODO:
|
||||
;; - pay attention to `interactive': its arg is run in an empty env.
|
||||
;; TODO:
|
||||
;; - canonize code in macro-expand so we don't have to handle (let (var) body)
|
||||
;; and other oddities.
|
||||
;; - Change new byte-code representation, so it directly gives the
|
||||
;; number of mandatory and optional arguments as well as whether or
|
||||
;; not there's a &rest arg.
|
||||
;; - warn about unused lexical vars.
|
||||
;; - clean up cconv-closure-convert-rec, especially the `let' binding part.
|
||||
;; - new byte codes for unwind-protect, catch, and condition-case so that
|
||||
;; closures aren't needed at all.
|
||||
;; - a reference to a var that is known statically to always hold a constant
|
||||
;; should be turned into a byte-constant rather than a byte-stack-ref.
|
||||
;; Hmm... right, that's called constant propagation and could be done here
|
||||
;; But when that constant is a function, we have to be careful to make sure
|
||||
;; the bytecomp only compiles it once.
|
||||
;; - Since we know here when a variable is not mutated, we could pass that
|
||||
;; info to the byte-compiler, e.g. by using a new `immutable-let'.
|
||||
;; - add tail-calls to bytecode.c and the bytecompiler.
|
||||
|
||||
;; (defmacro dlet (binders &rest body)
|
||||
;; ;; Works in both lexical and non-lexical mode.
|
||||
;; `(progn
|
||||
;; ,@(mapcar (lambda (binder)
|
||||
;; `(defvar ,(if (consp binder) (car binder) binder)))
|
||||
;; binders)
|
||||
;; (let ,binders ,@body)))
|
||||
|
||||
;; (defmacro llet (binders &rest body)
|
||||
;; ;; Only works in lexical-binding mode.
|
||||
;; `(funcall
|
||||
;; (lambda ,(mapcar (lambda (binder) (if (consp binder) (car binder) binder))
|
||||
;; binders)
|
||||
;; ,@body)
|
||||
;; ,@(mapcar (lambda (binder) (if (consp binder) (cadr binder)))
|
||||
;; binders)))
|
||||
|
||||
;; (defmacro letrec (binders &rest body)
|
||||
;; ;; Only useful in lexical-binding mode.
|
||||
;; ;; As a special-form, we could implement it more efficiently (and cleanly,
|
||||
;; ;; making the vars actually unbound during evaluation of the binders).
|
||||
;; `(let ,(mapcar (lambda (binder) (if (consp binder) (car binder) binder))
|
||||
;; binders)
|
||||
;; ,@(delq nil (mapcar (lambda (binder) (if (consp binder) `(setq ,@binder)))
|
||||
;; binders))
|
||||
;; ,@body))
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
|
||||
(defconst cconv-liftwhen 3
|
||||
(defconst cconv-liftwhen 6
|
||||
"Try to do lambda lifting if the number of arguments + free variables
|
||||
is less than this number.")
|
||||
;; List of all the variables that are both captured by a closure
|
||||
@ -212,13 +245,13 @@ Returns a form where all lambdas don't have any free variables."
|
||||
;; This function actually rewrites the tree.
|
||||
"Eliminates all free variables of all lambdas in given forms.
|
||||
Arguments:
|
||||
-- FORM is a piece of Elisp code after macroexpansion.
|
||||
-- LMENVS is a list of environments used for lambda-lifting. Initially empty.
|
||||
-- EMVRS is a list that contains mutated variables that are visible
|
||||
- FORM is a piece of Elisp code after macroexpansion.
|
||||
- LMENVS is a list of environments used for lambda-lifting. Initially empty.
|
||||
- EMVRS is a list that contains mutated variables that are visible
|
||||
within current environment.
|
||||
-- ENVS is an environment(list of free variables) of current closure.
|
||||
- ENVS is an environment(list of free variables) of current closure.
|
||||
Initially empty.
|
||||
-- FVRS is a list of variables to substitute in each context.
|
||||
- FVRS is a list of variables to substitute in each context.
|
||||
Initially empty.
|
||||
|
||||
Returns a form where all lambdas don't have any free variables."
|
||||
@ -270,10 +303,17 @@ Returns a form where all lambdas don't have any free variables."
|
||||
; lambda lifting condition
|
||||
(if (or (not fv) (< cconv-liftwhen (length funcvars)))
|
||||
; do not lift
|
||||
(cconv-closure-convert-rec
|
||||
value emvrs fvrs envs lmenvs)
|
||||
(progn
|
||||
;; (byte-compile-log-warning
|
||||
;; (format "Not λ-lifting `%S': %d > %d"
|
||||
;; var (length funcvars) cconv-liftwhen))
|
||||
|
||||
(cconv-closure-convert-rec
|
||||
value emvrs fvrs envs lmenvs))
|
||||
; lift
|
||||
(progn
|
||||
;; (byte-compile-log-warning
|
||||
;; (format "λ-lifting `%S'" var))
|
||||
(setq cconv-freevars-alist
|
||||
;; Now that we know we'll λ-lift, consume the
|
||||
;; freevar data.
|
||||
@ -579,6 +619,12 @@ Returns a form where all lambdas don't have any free variables."
|
||||
cdr-new))
|
||||
`(,callsym . ,(reverse cdr-new))))))
|
||||
|
||||
(`(interactive . ,forms)
|
||||
`(interactive
|
||||
,@(mapcar (lambda (form)
|
||||
(cconv-closure-convert-rec form nil nil nil nil))
|
||||
forms)))
|
||||
|
||||
(`(,func . ,body-forms) ; first element is function or whatever
|
||||
; function-like forms are:
|
||||
; or, and, if, progn, prog1, prog2,
|
||||
@ -608,23 +654,34 @@ Returns a form where all lambdas don't have any free variables."
|
||||
;; Only used to test the code in non-lexbind Emacs.
|
||||
(defalias 'byte-compile-not-lexical-var-p 'boundp))
|
||||
|
||||
(defun cconv-analyse-use (vardata form)
|
||||
(defun cconv-analyse-use (vardata form varkind)
|
||||
"Analyse the use of a variable.
|
||||
VARDATA should be (BINDER READ MUTATED CAPTURED CALLED).
|
||||
VARKIND is the name of the kind of variable.
|
||||
FORM is the parent form that binds this var."
|
||||
;; use = `(,binder ,read ,mutated ,captured ,called)
|
||||
(pcase vardata
|
||||
(`(,binder nil ,_ ,_ nil)
|
||||
;; FIXME: Don't warn about unused fun-args.
|
||||
;; FIXME: Don't warn about uninterned vars or _ vars.
|
||||
;; FIXME: This gives warnings in the wrong order and with wrong line
|
||||
;; number and without function name info.
|
||||
(byte-compile-log-warning (format "Unused variable %S" (car binder))))
|
||||
(`(,_ nil nil nil nil) nil)
|
||||
(`((,(and (pred (lambda (var) (eq ?_ (aref (symbol-name var) 0)))) var) . ,_)
|
||||
,_ ,_ ,_ ,_)
|
||||
(byte-compile-log-warning (format "%s `%S' not left unused" varkind var)))
|
||||
((or `(,_ ,_ ,_ ,_ ,_) dontcare) nil))
|
||||
(pcase vardata
|
||||
(`((,var . ,_) nil ,_ ,_ nil)
|
||||
;; FIXME: This gives warnings in the wrong order, with imprecise line
|
||||
;; numbers and without function name info.
|
||||
(unless (or ;; Uninterned symbols typically come from macro-expansion, so
|
||||
;; it is often non-trivial for the programmer to avoid such
|
||||
;; unused vars.
|
||||
(not (intern-soft var))
|
||||
(eq ?_ (aref (symbol-name var) 0)))
|
||||
(byte-compile-log-warning (format "Unused lexical %s `%S'"
|
||||
varkind var))))
|
||||
;; If it's unused, there's no point converting it into a cons-cell, even if
|
||||
;; it's captures and mutated.
|
||||
;; it's captured and mutated.
|
||||
(`(,binder ,_ t t ,_)
|
||||
(push (cons binder form) cconv-captured+mutated))
|
||||
(`(,(and binder `(,_ (function (lambda . ,_)))) nil nil nil t)
|
||||
;; This is very rare in typical Elisp code. It's probably not really
|
||||
;; worth the trouble to try and use lambda-lifting in Elisp, but
|
||||
;; since we coded it up, we might as well use it.
|
||||
(push (cons binder form) cconv-lambda-candidates))
|
||||
(`(,_ ,_ ,_ ,_ ,_) nil)
|
||||
(dontcare)))
|
||||
@ -654,7 +711,7 @@ Returns a form where all lambdas don't have any free variables."
|
||||
(cconv-analyse-form form newenv))
|
||||
;; Summarize resulting data about arguments.
|
||||
(dolist (vardata newvars)
|
||||
(cconv-analyse-use vardata parentform))
|
||||
(cconv-analyse-use vardata parentform "argument"))
|
||||
;; Transfer uses collected in `envcopy' (via `newenv') back to `env';
|
||||
;; and compute free variables.
|
||||
(while env
|
||||
@ -673,8 +730,8 @@ Returns a form where all lambdas don't have any free variables."
|
||||
(defun cconv-analyse-form (form env)
|
||||
"Find mutated variables and variables captured by closure.
|
||||
Analyse lambdas if they are suitable for lambda lifting.
|
||||
-- FORM is a piece of Elisp code after macroexpansion.
|
||||
-- ENV is an alist mapping each enclosing lexical variable to its info.
|
||||
- FORM is a piece of Elisp code after macroexpansion.
|
||||
- ENV is an alist mapping each enclosing lexical variable to its info.
|
||||
I.e. each element has the form (VAR . (READ MUTATED CAPTURED CALLED)).
|
||||
This function does not return anything but instead fills the
|
||||
`cconv-captured+mutated' and `cconv-lambda-candidates' variables
|
||||
@ -707,7 +764,7 @@ and updates the data stored in ENV."
|
||||
(cconv-analyse-form form env))
|
||||
|
||||
(dolist (vardata newvars)
|
||||
(cconv-analyse-use vardata form))))
|
||||
(cconv-analyse-use vardata form "variable"))))
|
||||
|
||||
; defun special form
|
||||
(`(,(or `defun `defmacro) ,func ,vrs . ,body-forms)
|
||||
@ -736,8 +793,7 @@ and updates the data stored in ENV."
|
||||
|
||||
(`(cond . ,cond-forms) ; cond special form
|
||||
(dolist (forms cond-forms)
|
||||
(dolist (form forms)
|
||||
(cconv-analyse-form form env))))
|
||||
(dolist (form forms) (cconv-analyse-form form env))))
|
||||
|
||||
(`(quote . ,_) nil) ; quote form
|
||||
(`(function . ,_) nil) ; same as quote
|
||||
@ -773,12 +829,18 @@ and updates the data stored in ENV."
|
||||
(if fdata
|
||||
(setf (nth 4 fdata) t)
|
||||
(cconv-analyse-form fun env)))
|
||||
(dolist (form args)
|
||||
(cconv-analyse-form form env)))
|
||||
(dolist (form args) (cconv-analyse-form form env)))
|
||||
|
||||
(`(interactive . ,forms)
|
||||
;; These appear within the function body but they don't have access
|
||||
;; to the function's arguments.
|
||||
;; We could extend this to allow interactive specs to refer to
|
||||
;; variables in the function's enclosing environment, but it doesn't
|
||||
;; seem worth the trouble.
|
||||
(dolist (form forms) (cconv-analyse-form form nil)))
|
||||
|
||||
(`(,_ . ,body-forms) ; First element is a function or whatever.
|
||||
(dolist (form body-forms)
|
||||
(cconv-analyse-form form env)))
|
||||
(dolist (form body-forms) (cconv-analyse-form form env)))
|
||||
|
||||
((pred symbolp)
|
||||
(let ((dv (assq form env))) ; dv = declared and visible
|
||||
|
@ -431,7 +431,7 @@ and otherwise defers to REST which is a list of branches of the form
|
||||
rest)))))))
|
||||
((eq 'match (caar matches))
|
||||
(let* ((popmatches (pop matches))
|
||||
(op (car popmatches)) (cdrpopmatches (cdr popmatches))
|
||||
(_op (car popmatches)) (cdrpopmatches (cdr popmatches))
|
||||
(sym (car cdrpopmatches))
|
||||
(upat (cdr cdrpopmatches)))
|
||||
(cond
|
||||
@ -520,7 +520,7 @@ and otherwise defers to REST which is a list of branches of the form
|
||||
(pcase--u1 `((match ,sym . ,(cadr upat)))
|
||||
;; FIXME: This codegen is not careful to share its
|
||||
;; code if used several times: code blow up is likely.
|
||||
(lambda (vars)
|
||||
(lambda (_vars)
|
||||
;; `vars' will likely contain bindings which are
|
||||
;; not always available in other paths to
|
||||
;; `rest', so there' no point trying to pass
|
||||
|
@ -119,8 +119,11 @@ ARGLIST can also be t or a string of the form \"(FUN ARG1 ARG2 ...)\"."
|
||||
(cdr arg))
|
||||
arg)
|
||||
(let ((name (symbol-name arg)))
|
||||
(if (string-match "\\`&" name) arg
|
||||
(intern (upcase name))))))
|
||||
(cond
|
||||
((string-match "\\`&" name) arg)
|
||||
((string-match "\\`_" name)
|
||||
(intern (upcase (substring name 1))))
|
||||
(t (intern (upcase name)))))))
|
||||
arglist)))
|
||||
|
||||
;; Could be this, if we make symbol-file do the work below.
|
||||
|
@ -210,7 +210,7 @@ You should give VAR a non-nil `risky-local-variable' property."
|
||||
((vectorp table) ;Obarray.
|
||||
(lambda (sym) (funcall pred (concat prefix (symbol-name sym)))))
|
||||
((hash-table-p table)
|
||||
(lambda (s v) (funcall pred (concat prefix s))))
|
||||
(lambda (s _v) (funcall pred (concat prefix s))))
|
||||
((functionp table)
|
||||
(lambda (s) (funcall pred (concat prefix s))))
|
||||
(t ;Lists and alists.
|
||||
@ -681,7 +681,7 @@ scroll the window of possible completions."
|
||||
t)
|
||||
(t t)))))
|
||||
|
||||
(defun completion--flush-all-sorted-completions (&rest ignore)
|
||||
(defun completion--flush-all-sorted-completions (&rest _ignore)
|
||||
(setq completion-cycling nil)
|
||||
(setq completion-all-sorted-completions nil))
|
||||
|
||||
@ -1313,7 +1313,7 @@ The completion method is determined by `completion-at-point-functions'."
|
||||
(concat "\\(?:^\\|[^$]\\(?:\\$\\$\\)*\\)"
|
||||
"$\\([[:alnum:]_]*\\|{\\([^}]*\\)\\)\\'"))
|
||||
|
||||
(defun completion--embedded-envvar-table (string pred action)
|
||||
(defun completion--embedded-envvar-table (string _pred action)
|
||||
"Completion table for envvars embedded in a string.
|
||||
The envvar syntax (and escaping) rules followed by this table are the
|
||||
same as `substitute-in-file-name'."
|
||||
@ -1726,13 +1726,13 @@ Like `internal-complete-buffer', but removes BUFFER from the completion list."
|
||||
|
||||
;;; Old-style completion, used in Emacs-21 and Emacs-22.
|
||||
|
||||
(defun completion-emacs21-try-completion (string table pred point)
|
||||
(defun completion-emacs21-try-completion (string table pred _point)
|
||||
(let ((completion (try-completion string table pred)))
|
||||
(if (stringp completion)
|
||||
(cons completion (length completion))
|
||||
completion)))
|
||||
|
||||
(defun completion-emacs21-all-completions (string table pred point)
|
||||
(defun completion-emacs21-all-completions (string table pred _point)
|
||||
(completion-hilit-commonality
|
||||
(all-completions string table pred)
|
||||
(length string)
|
||||
@ -1817,7 +1817,7 @@ Return the new suffix."
|
||||
(let* ((beforepoint (substring string 0 point))
|
||||
(afterpoint (substring string point))
|
||||
(bounds (completion-boundaries beforepoint table pred afterpoint))
|
||||
(suffix (substring afterpoint (cdr bounds)))
|
||||
;; (suffix (substring afterpoint (cdr bounds)))
|
||||
(prefix (substring beforepoint 0 (car bounds)))
|
||||
(pattern (delete
|
||||
"" (list (substring beforepoint (car bounds))
|
||||
@ -2006,7 +2006,7 @@ filter out additional entries (because TABLE migth not obey PRED)."
|
||||
;; The prefix has no completions at all, so we should try and fix
|
||||
;; that first.
|
||||
(let ((substring (substring prefix 0 -1)))
|
||||
(destructuring-bind (subpat suball subprefix subsuffix)
|
||||
(destructuring-bind (subpat suball subprefix _subsuffix)
|
||||
(completion-pcm--find-all-completions
|
||||
substring table pred (length substring) filter)
|
||||
(let ((sep (aref prefix (1- (length prefix))))
|
||||
@ -2071,7 +2071,7 @@ filter out additional entries (because TABLE migth not obey PRED)."
|
||||
(list pattern all prefix suffix)))))
|
||||
|
||||
(defun completion-pcm-all-completions (string table pred point)
|
||||
(destructuring-bind (pattern all &optional prefix suffix)
|
||||
(destructuring-bind (pattern all &optional prefix _suffix)
|
||||
(completion-pcm--find-all-completions string table pred point)
|
||||
(when all
|
||||
(nconc (completion-pcm--hilit-commonality pattern all)
|
||||
@ -2246,14 +2246,14 @@ filter out additional entries (because TABLE migth not obey PRED)."
|
||||
(list all pattern prefix suffix (car bounds))))
|
||||
|
||||
(defun completion-substring-try-completion (string table pred point)
|
||||
(destructuring-bind (all pattern prefix suffix carbounds)
|
||||
(destructuring-bind (all pattern prefix suffix _carbounds)
|
||||
(completion-substring--all-completions string table pred point)
|
||||
(if minibuffer-completing-file-name
|
||||
(setq all (completion-pcm--filename-try-filter all)))
|
||||
(completion-pcm--merge-try pattern all prefix suffix)))
|
||||
|
||||
(defun completion-substring-all-completions (string table pred point)
|
||||
(destructuring-bind (all pattern prefix suffix carbounds)
|
||||
(destructuring-bind (all pattern prefix _suffix _carbounds)
|
||||
(completion-substring--all-completions string table pred point)
|
||||
(when all
|
||||
(nconc (completion-pcm--hilit-commonality pattern all)
|
||||
@ -2290,12 +2290,12 @@ filter out additional entries (because TABLE migth not obey PRED)."
|
||||
(concat (substring str 0 (car bounds))
|
||||
(mapconcat 'string (substring str (car bounds)) sep))))))))
|
||||
|
||||
(defun completion-initials-all-completions (string table pred point)
|
||||
(defun completion-initials-all-completions (string table pred _point)
|
||||
(let ((newstr (completion-initials-expand string table pred)))
|
||||
(when newstr
|
||||
(completion-pcm-all-completions newstr table pred (length newstr)))))
|
||||
|
||||
(defun completion-initials-try-completion (string table pred point)
|
||||
(defun completion-initials-try-completion (string table pred _point)
|
||||
(let ((newstr (completion-initials-expand string table pred)))
|
||||
(when newstr
|
||||
(completion-pcm-try-completion newstr table pred (length newstr)))))
|
||||
|
21
lisp/mpc.el
21
lisp/mpc.el
@ -357,14 +357,14 @@ which will be concatenated with proper quoting before passing them to MPD."
|
||||
(mapconcat 'mpc--proc-quote-string cmd " "))
|
||||
"\n")))
|
||||
(if callback
|
||||
(let ((buf (current-buffer)))
|
||||
;; (let ((buf (current-buffer)))
|
||||
(process-put proc 'callback
|
||||
callback
|
||||
;; (lambda ()
|
||||
;; (funcall callback
|
||||
;; (prog1 (current-buffer)
|
||||
;; (set-buffer buf))))
|
||||
))
|
||||
;; (set-buffer buf)))))
|
||||
)
|
||||
;; If `callback' is nil, we're executing synchronously.
|
||||
(process-put proc 'callback 'ignore)
|
||||
;; This returns the process's buffer.
|
||||
@ -600,7 +600,7 @@ The songs are returned as alists."
|
||||
(cond
|
||||
((eq tag 'Playlist)
|
||||
;; Special case for pseudo-tag playlist.
|
||||
(let ((l (condition-case err
|
||||
(let ((l (condition-case nil
|
||||
(mpc-proc-buf-to-alists
|
||||
(mpc-proc-cmd (list "listplaylistinfo" value)))
|
||||
(mpc-proc-error
|
||||
@ -633,7 +633,7 @@ The songs are returned as alists."
|
||||
(mpc-union (mpc-cmd-find tag1 value)
|
||||
(mpc-cmd-find tag2 value))))
|
||||
(t
|
||||
(condition-case err
|
||||
(condition-case nil
|
||||
(mpc-proc-buf-to-alists
|
||||
(mpc-proc-cmd (list "find" (symbol-name tag) value)))
|
||||
(mpc-proc-error
|
||||
@ -935,7 +935,7 @@ If PLAYLIST is t or nil or missing, use the main playlist."
|
||||
|
||||
(defun mpc-tempfiles-clean ()
|
||||
(let ((live ()))
|
||||
(maphash (lambda (k v) (push v live)) mpc-tempfiles-reftable)
|
||||
(maphash (lambda (_k v) (push v live)) mpc-tempfiles-reftable)
|
||||
(dolist (f mpc-tempfiles)
|
||||
(unless (member f live) (ignore-errors (delete-file f))))
|
||||
(setq mpc-tempfiles live)))
|
||||
@ -1159,7 +1159,7 @@ If PLAYLIST is t or nil or missing, use the main playlist."
|
||||
(mpc-status-mode))
|
||||
(mpc-proc-buffer (mpc-proc) 'status buf))
|
||||
(if (null songs-win) (pop-to-buffer buf)
|
||||
(let ((win (split-window songs-win 20 t)))
|
||||
(let ((_win (split-window songs-win 20 t)))
|
||||
(set-window-dedicated-p songs-win nil)
|
||||
(set-window-buffer songs-win buf)
|
||||
(set-window-dedicated-p songs-win 'soft)))))
|
||||
@ -2385,15 +2385,13 @@ This is used so that they can be compared with `eq', which is needed for
|
||||
(mpc--faster-stop)
|
||||
(mpc-status-refresh) (mpc-proc-sync)
|
||||
(let* (songid ;The ID of the currently ffwd/rewinding song.
|
||||
songnb ;The position of that song in the playlist.
|
||||
songduration ;The duration of that song.
|
||||
songtime ;The time of the song last time we ran.
|
||||
oldtime ;The timeoftheday last time we ran.
|
||||
prevsongid) ;The song we're in the process leaving.
|
||||
(let ((fun
|
||||
(lambda ()
|
||||
(let ((newsongid (cdr (assq 'songid mpc-status)))
|
||||
(newsongnb (cdr (assq 'song mpc-status))))
|
||||
(let ((newsongid (cdr (assq 'songid mpc-status))))
|
||||
|
||||
(if (and (equal prevsongid newsongid)
|
||||
(not (equal prevsongid songid)))
|
||||
@ -2444,8 +2442,7 @@ This is used so that they can be compared with `eq', which is needed for
|
||||
(mpc-proc-cmd
|
||||
(list "seekid" songid songtime)
|
||||
'mpc-status-refresh)
|
||||
(mpc-proc-error (mpc-status-refresh)))))))
|
||||
(setq songnb newsongnb)))))
|
||||
(mpc-proc-error (mpc-status-refresh)))))))))))
|
||||
(setq mpc--faster-toggle-forward (> step 0))
|
||||
(funcall fun) ;Initialize values.
|
||||
(setq mpc--faster-toggle-timer
|
||||
|
@ -418,10 +418,11 @@ If CLIENT is non-nil, add a description of it to the logged message."
|
||||
(server-delete-client proc 'noframe)))) ; Let delete-frame delete the frame later.
|
||||
|
||||
(defun server-handle-suspend-tty (terminal)
|
||||
"Notify the emacsclient process to suspend itself when its tty device is suspended."
|
||||
"Notify the client process that its tty device is suspended."
|
||||
(dolist (proc (server-clients-with 'terminal terminal))
|
||||
(server-log (format "server-handle-suspend-tty, terminal %s" terminal) proc)
|
||||
(condition-case err
|
||||
(server-log (format "server-handle-suspend-tty, terminal %s" terminal)
|
||||
proc)
|
||||
(condition-case nil
|
||||
(server-send-string proc "-suspend \n")
|
||||
(file-error ;The pipe/socket was closed.
|
||||
(ignore-errors (server-delete-client proc))))))
|
||||
@ -1207,7 +1208,10 @@ so don't mark these buffers specially, just visit them normally."
|
||||
(process-put proc 'buffers
|
||||
(nconc (process-get proc 'buffers) client-record)))
|
||||
client-record))
|
||||
|
||||
|
||||
(defvar server-kill-buffer-running nil
|
||||
"Non-nil while `server-kill-buffer' or `server-buffer-done' is running.")
|
||||
|
||||
(defun server-buffer-done (buffer &optional for-killing)
|
||||
"Mark BUFFER as \"done\" for its client(s).
|
||||
This buries the buffer, then returns a list of the form (NEXT-BUFFER KILLED).
|
||||
@ -1329,9 +1333,6 @@ specifically for the clients and did not exist before their request for it."
|
||||
(setq live-client t))))
|
||||
(yes-or-no-p "This Emacs session has clients; exit anyway? ")))
|
||||
|
||||
(defvar server-kill-buffer-running nil
|
||||
"Non-nil while `server-kill-buffer' or `server-buffer-done' is running.")
|
||||
|
||||
(defun server-kill-buffer ()
|
||||
"Remove the current buffer from its clients' buffer list.
|
||||
Designed to be added to `kill-buffer-hook'."
|
||||
|
@ -1,3 +1,9 @@
|
||||
2011-03-01 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* callint.c (quotify_arg): Simplify the logic.
|
||||
(Fcall_interactively): Use lexical binding when evaluating the
|
||||
interactive spec of a lexically bound function.
|
||||
|
||||
2011-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* eval.c (Qcurry): Remove.
|
||||
|
@ -121,8 +121,9 @@ usage: (interactive &optional ARGS) */)
|
||||
Lisp_Object
|
||||
quotify_arg (register Lisp_Object exp)
|
||||
{
|
||||
if (!INTEGERP (exp) && !STRINGP (exp)
|
||||
&& !NILP (exp) && !EQ (exp, Qt))
|
||||
if (CONSP (exp)
|
||||
|| (SYMBOLP (exp)
|
||||
&& !NILP (exp) && !EQ (exp, Qt)))
|
||||
return Fcons (Qquote, Fcons (exp, Qnil));
|
||||
|
||||
return exp;
|
||||
@ -169,6 +170,9 @@ check_mark (int for_region)
|
||||
static void
|
||||
fix_command (Lisp_Object input, Lisp_Object values)
|
||||
{
|
||||
/* FIXME: Instead of this ugly hack, we should provide a way for an
|
||||
interactive spec to return an expression that will re-build the args
|
||||
without user intervention. */
|
||||
if (CONSP (input))
|
||||
{
|
||||
Lisp_Object car;
|
||||
@ -331,11 +335,14 @@ invoke it. If KEYS is omitted or nil, the return value of
|
||||
else
|
||||
{
|
||||
Lisp_Object input;
|
||||
Lisp_Object funval = Findirect_function (function, Qt);
|
||||
i = num_input_events;
|
||||
input = specs;
|
||||
/* Compute the arg values using the user's expression. */
|
||||
GCPRO2 (input, filter_specs);
|
||||
specs = Feval (specs, Qnil); /* FIXME: lexbind */
|
||||
specs = Feval (specs,
|
||||
CONSP (funval) && EQ (Qclosure, XCAR (funval))
|
||||
? Qt : Qnil);
|
||||
UNGCPRO;
|
||||
if (i != num_input_events || !NILP (record_flag))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user