Merge remote-tracking branch 'origin/master' into feature/package+vc

This commit is contained in:
Philip Kaludercic 2022-10-18 21:53:25 +02:00
commit 65fa87329c
No known key found for this signature in database
GPG key ID: F2C3CC513DB89F66
61 changed files with 2138 additions and 724 deletions

2
.gitignore vendored
View file

@ -324,7 +324,7 @@ lib-src/seccomp-filter-exec.pfc
/etc/*.gschema.valid
# Ignore directory made by admin/make-manuals.
manual/
/manual/
# Ignore Finder files on MacOS.
.DS_Store

View file

@ -52,14 +52,14 @@
# make bootstrap
# Removes all the compiled files to force a new bootstrap from a
# clean slate, and then build in the normal way. If the FAST Make
# variable is set, then the config.cache file isn't removed. This
# allows you to say
# variable is set, then the autom4te.cache directory and the
# config.cache file are not removed. This lets you say
#
# ./configure -C
# make FAST=true bootstrap
#
# and use the cached results from the configure run, which is much
# faster.
# faster though it does not work in general.
#
# make docs
# Make Emacs documentation files from their sources; requires makeinfo.
@ -1040,7 +1040,7 @@ bootstrap-clean: $(distclean_dirs:=_bootstrap-clean)
rm -f ${srcdir}/etc/refcards/emacsver.tex
rm -rf native-lisp/ lisp/leim/ja-dic/
ifndef FAST
rm -f config.cache
rm -fr autom4te.cache config.cache
endif
${top_bootclean}

View file

@ -2821,6 +2821,24 @@ strings incorrectly. You should then avoid adding Emacs Lisp code
that modifies the coding system in other ways, such as calls to
@code{set-language-environment}.
An alternative to using non-@acronym{ASCII} characters directly is
to use one of the character escape syntaxes described in
@pxref{General Escape Syntax,,, elisp, The Emacs Lisp Reference
Manual}, as they allow all Unicode codepoints to be specified using
only @acronym{ASCII} characters.
To bind non-@acronym{ASCII} keys, you must use a vector (@pxref{Init
Rebinding}). The string syntax cannot be used, since the
non-@acronym{ASCII} characters will be interpreted as meta keys. For
instance:
@example
(global-set-key [?@var{char}] 'some-function)
@end example
@noindent
Type @kbd{C-q}, followed by the key you want to bind, to insert @var{char}.
@node Early Init File
@subsection The Early Init File
@cindex early init file

View file

@ -1421,27 +1421,38 @@ nor comments). The default value is @code{code}.
Completion is normally done in the minibuffer (@pxref{Completion}),
but you can also complete symbol names in ordinary Emacs buffers.
@cindex tags-based completion
@kindex M-TAB
@kindex C-M-i
In programming language modes, type @kbd{C-M-i} or @kbd{M-@key{TAB}}
to complete the partial symbol before point. On graphical displays,
the @kbd{M-@key{TAB}} key is usually reserved by the window manager
for switching graphical windows, so you should type @kbd{C-M-i} or
@kbd{@key{ESC} @key{TAB}} instead.
@cindex tags-based completion
@findex completion-at-point@r{, in programming language modes}
@cindex Lisp symbol completion
@cindex completion (Lisp symbols)
In most programming language modes, @kbd{C-M-i} (or
@kbd{M-@key{TAB}}) invokes the command @code{completion-at-point},
which generates its completion list in a flexible way. If Semantic
mode is enabled, it tries to use the Semantic parser data for
completion (@pxref{Semantic}). If Semantic mode is not enabled or
fails at performing completion, it tries to complete using the
selected tags table (@pxref{Tags Tables}). If in Emacs Lisp mode, it
performs completion using the function, variable, or property names
defined in the current Emacs session.
@kbd{M-@key{TAB}}@footnote{
On graphical displays, the @kbd{M-@key{TAB}} key is usually reserved
by the window manager for switching graphical windows, so you should
type @kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}} instead.
}) invokes the command @code{completion-at-point}, which generates the
list of possible completions for the symbol at point. This command
uses the available support facilities to come up with the completion
candidates:
@itemize @bullet
@item
If Semantic mode is enabled (@pxref{Semantic}), the command tries to
use the Semantic parser data for completion.
@item
If Semantic mode is not enabled or fails at performing completion, the
command tries to complete using the selected tags table (@pxref{Tags
Tables}); you need to visit the tags table with @w{@kbd{M-x
visit-tags-table}} for that to work.
@item
In Emacs Lisp mode, the command performs completion using the
function, variable, or property names defined in the current Emacs
session.
@end itemize
In all other respects, in-buffer symbol completion behaves like
minibuffer completion. For instance, if Emacs cannot complete to

View file

@ -843,6 +843,14 @@ native compilation of that file. In addition, a similar variable
file. If both @code{no-byte-compile} and @code{no-native-compile} are
specified, the former takes precedence.
@cindex native compilation, prevent writing @file{*.eln} files
Sometimes there could be a need to prevent the native compilation
from writing its results, the @file{*.eln} files, into a subdirectory
of @code{user-emacs-directory} (@pxref{Init File}). You can do that
by either changing the value of @code{native-comp-eln-load-path}
(@pxref{Native-Compilation Variables}) or by temporarily pointing the
@env{HOME} environment variable to a non-existing directory.
@menu
* Native-Compilation Functions:: Functions to natively-compile Lisp.
* Native-Compilation Variables:: Variables controlling native compilation.
@ -1075,3 +1083,13 @@ subprocesses that are still running, thus preventing the corresponding
@file{.eln} files from being written. If the value is @code{nil}, the
default, Emacs will kill these subprocesses without querying.
@end defopt
The variable @code{native-comp-eln-load-path} holds the list of
directories where Emacs looks for the @file{*.eln} files
(@pxref{Library Search}); in that role it is the equivalent of
@code{load-path} used to look for @file{*.el} and @file{*.elc} files.
The directories in this list are also used for writing the
@file{*.eln} files produced by asynchronous native-compilation;
specifically, Emacs will write these files into the first writable
directory in the list. Thus, you can control where native-compilation
stores the results by changing the value of this variable.

View file

@ -3146,9 +3146,10 @@ match found by @var{matcher} acts as the anchor for further searches
specified by @var{anchored-highlighter}. @var{anchored-highlighter}
is a list of the following form:
@c Don't wrap the line in the next @example, because that tends to
@c produce ugly indentation in Info
@example
(@var{anchored-matcher} @var{pre-form} @var{post-form}
@var{subexp-highlighters}@dots{})
(@var{anchored-matcher} @var{pre-form} @var{post-form} @var{subexp-highlighters}@dots{})
@end example
Here, @var{anchored-matcher}, like @var{matcher}, is either a regular

View file

@ -1238,6 +1238,9 @@ any given seed, the @code{random} function always generates the same
sequence of numbers. By default, Emacs initializes the random seed at
startup, in such a way that the sequence of values of @code{random}
(with overwhelming likelihood) differs in each Emacs run.
The random seed is typically initialized from system entropy;
however, on obsolescent platforms lacking entropy pools,
the seed is taken from less-random volatile data such as the current time.
Sometimes you want the random number sequence to be repeatable. For
example, when debugging a program whose behavior depends on the random
@ -1256,12 +1259,45 @@ nonnegative and less than @var{limit}. Otherwise, the value might be
any fixnum, i.e., any integer from @code{most-negative-fixnum} through
@code{most-positive-fixnum} (@pxref{Integer Basics}).
If @var{limit} is @code{t}, it means to choose a new seed as if Emacs
were restarting, typically from the system entropy. On systems
lacking entropy pools, choose the seed from less-random volatile data
such as the current time.
If @var{limit} is a string, it means to choose a new seed based on the
string's contents.
string's contents. This causes later calls to @code{random} to return
a reproducible sequence of results.
If @var{limit} is @code{t}, it means to choose a new seed as if Emacs
were restarting. This causes later calls to @code{random} to return
an unpredictable sequence of results.
@end defun
If you need a random nonce for cryptographic purposes, using
@code{random} is typically not the best approach, for several reasons:
@itemize @bullet
@item
Although you can use @code{(random t)} to consult system entropy,
doing so can adversely affect other parts of your program that benefit
from reproducible results.
@item
The system-dependent pseudo-random number generator (PRNG) used by
@code{random} is not necessarily suitable for cryptography.
@item
A call to @code{(random t)} does not give direct access to system
entropy; the entropy is passed through the system-dependent PRNG, thus
possibly biasing the results.
@item
On typical platforms the random seed contains only 32 bits, which is
typically narrower than an Emacs fixnum, and is not nearly enough for
cryptographic purposes.
@item
A @code{(random t)} call leaves information about the nonce scattered
about Emacs's internal state, increasing the size of the internal
attack surface.
@item
On obsolescent platforms lacking entropy pools, @code{(random t)} is
seeded from a cryptographically weak source.
@end itemize

View file

@ -2239,9 +2239,26 @@ still respecting file-local variables (@pxref{File Local Variables}).
@cindex connection local variables
Connection-local variables provide a general mechanism for different
variable settings in buffers with a remote connection. They are bound
variable settings in buffers with a remote connection (@pxref{Remote
Files,, Remote Files, emacs, The GNU Emacs Manual}). They are bound
and set depending on the remote connection a buffer is dedicated to.
@menu
* Connection Local Profiles:: Storing variable settings to
apply to connections.
* Applying Connection Local Variables:: Using connection-local values
in your code.
@end menu
@node Connection Local Profiles
@subsection Connection Local Profiles
@cindex connection local profiles
Emacs uses connection-local profiles to store the variable settings
to apply to particular connections. You can then associate these with
remote connections by defining the criteria when they should apply,
using @code{connection-local-set-profiles}.
@defun connection-local-set-profile-variables profile variables
This function defines a set of variable settings for the connection
@var{profile}, which is a symbol. You can later assign the connection
@ -2311,13 +2328,13 @@ always applies. Example:
@example
@group
(connection-local-set-profiles
'(:application 'tramp :protocol "ssh" :machine "localhost")
'(:application tramp :protocol "ssh" :machine "localhost")
'remote-bash 'remote-null-device)
@end group
@group
(connection-local-set-profiles
'(:application 'tramp :protocol "sudo"
'(:application tramp :protocol "sudo"
:user "root" :machine "localhost")
'remote-ksh 'remote-null-device)
@end group
@ -2329,13 +2346,13 @@ Therefore, the example above would be equivalent to
@example
@group
(connection-local-set-profiles
'(:application 'tramp :protocol "ssh" :machine "localhost")
'(:application tramp :protocol "ssh" :machine "localhost")
'remote-bash)
@end group
@group
(connection-local-set-profiles
'(:application 'tramp :protocol "sudo"
'(:application tramp :protocol "sudo"
:user "root" :machine "localhost")
'remote-ksh)
@end group
@ -2356,6 +2373,14 @@ names. The function @code{connection-local-set-profiles} updates this
list.
@end deffn
@node Applying Connection Local Variables
@subsection Applying Connection Local Variables
@cindex connection local variables, applying
When writing connection-aware code, you'll need to collect, and
possibly apply, any connection-local variables. There are several
ways to do this, as described below.
@defun hack-connection-local-variables criteria
This function collects applicable connection-local variables
associated with @var{criteria} in
@ -2365,7 +2390,7 @@ Example:
@example
@group
(hack-connection-local-variables
'(:application 'tramp :protocol "ssh" :machine "localhost"))
'(:application tramp :protocol "ssh" :machine "localhost"))
@end group
@group
@ -2384,41 +2409,13 @@ This function looks for connection-local variables according to
@var{criteria}, and immediately applies them in the current buffer.
@end defun
@defmac with-connection-local-variables &rest body
All connection-local variables, which are specified by
@code{default-directory}, are applied.
@defmac with-connection-local-application-variables application &rest body
Apply all connection-local variables for @code{application}, which are
specified by @code{default-directory}.
After that, @var{body} is executed, and the connection-local variables
are unwound. Example:
@example
@group
(connection-local-set-profile-variables
'remote-perl
'((perl-command-name . "/usr/local/bin/perl")
(perl-command-switch . "-e %s")))
@end group
@group
(connection-local-set-profiles
'(:application 'tramp :protocol "ssh" :machine "remotehost")
'remote-perl)
@end group
@group
(let ((default-directory "/ssh:remotehost:/working/dir/"))
(with-connection-local-variables
do something useful))
@end group
@end example
@end defmac
@defvar connection-local-default-application
The default application, a symbol, to be applied in
@code{with-connection-local-variables}. It defaults to @code{tramp},
but in case you want to overwrite Tramp's settings temporarily, you
could let-bind it like
@example
@group
(connection-local-set-profile-variables
@ -2429,17 +2426,74 @@ could let-bind it like
@group
(connection-local-set-profiles
'(:application 'my-app :protocol "ssh" :machine "remotehost")
'(:application my-app :protocol "ssh" :machine "remotehost")
'my-remote-perl)
@end group
@group
(let ((default-directory "/ssh:remotehost:/working/dir/")
(connection-local-default-application 'my-app))
(with-connection-local-variables
(let ((default-directory "/ssh:remotehost:/working/dir/"))
(with-connection-local-application-variables 'my-app
do something useful))
@end group
@end example
@end defmac
@defvar connection-local-default-application
The default application, a symbol, to be applied in
@code{with-connection-local-variables}. It defaults to @code{tramp},
but you can let-bind it to change the application temporarily
(@pxref{Local Variables}).
This variable must not be changed globally.
@end defvar
@defmac with-connection-local-variables &rest body
This is equivalent to
@code{with-connection-local-application-variables}, but uses
@code{connection-local-default-application} for the application.
@end defmac
@defmac setq-connection-local [symbol form]@dots{}
This macro sets each @var{symbol} connection-locally to the result of
evaluating the corresponding @var{form}, using the connection-local
profile specified in @code{connection-local-profile-name-for-setq}; if
the profile name is @code{nil}, this macro will just set the variables
normally, as with @code{setq} (@pxref{Setting Variables}).
For example, you can use this macro in combination with
@code{with-connection-local-variables} or
@code{with-connection-local-application-variables} to lazily
initialize connection-local settings:
@example
@group
(defvar my-app-variable nil)
(connection-local-set-profile-variables
'my-app-connection-default-profile
'((my-app-variable . nil)))
(connection-local-set-profiles
'(:application my-app)
'my-app-connection-default-profile)
@end group
@group
(defun my-app-get-variable ()
(with-connection-local-application-variables 'my-app
(or my-app-variable
(setq-connection-local my-app-variable
do something useful))))
@end group
@end example
@end defmac
@defvar connection-local-profile-name-for-setq
The connection-local profile name, a symbol, to use when setting
variables via @code{setq-connection-local}. This is let-bound in the
body of @code{with-connection-local-variables}, but you can also
let-bind it yourself if you'd like to set variables on a different
profile.
This variable must not be changed globally.
@end defvar

View file

@ -439,11 +439,6 @@ Print the current local time as a human-readable string. This command
is similar to, but slightly different from, the GNU Coreutils
@command{date} command.
@item define
@cmindex define
Define a variable alias.
@xref{Variable Aliases, , , elisp, The Emacs Lisp Reference Manual}.
@item diff
@cmindex diff
Compare files using Emacs's internal @code{diff} (not to be confused
@ -699,10 +694,18 @@ used for comparing lists of strings.
This command can be loaded as part of the eshell-xtra module, which is
disabled by default.
@item set
@cmindex set
Set variable values, using the function @code{set} like a command
(@pxref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}).
A variable name can be a symbol, in which case it refers to a Lisp
variable, or a string, referring to an environment variable
(@pxref{Arguments}).
@item setq
@cmindex setq
Set variable values, using the function @code{setq} like a command.
@xref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}.
Set variable values, using the function @code{setq} like a command
(@pxref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}).
@item source
@cmindex source
@ -748,7 +751,9 @@ disabled by default.
@item unset
@cmindex unset
Unset an environment variable.
Unset one or more variables. As with @command{set}, a variable name
can be a symbol, in which case it refers to a Lisp variable, or a
string, referring to an environment variable.
@item wait
@cmindex wait
@ -886,12 +891,35 @@ For example, you could handle a subset of the options for the
@node Variables
@section Variables
Since Eshell is just an Emacs @acronym{REPL}@footnote{
@vindex eshell-prefer-lisp-variables
Since Eshell is a combination of an Emacs @acronym{REPL}@footnote{
Short for ``Read-Eval-Print Loop''.
}
, it does not have its own scope, and simply stores variables the same
you would in an Elisp program. Eshell provides a command version of
@code{setq} for convenience.
} and a command shell, it can refer to variables from two different
sources: ordinary Emacs Lisp variables, as well as environment
variables. By default, when using a variable in Eshell, it will first
look in the list of built-in variables, then in the list of
environment variables, and finally in the list of Lisp variables. If
you would prefer to use Lisp variables over environment variables, you
can set @code{eshell-prefer-lisp-variables} to @code{t}.
You can set variables in a few different ways. To set a Lisp
variable, you can use the command @samp{setq @var{name} @var{value}},
which works much like its Lisp counterpart (@pxref{Setting Variables,
, , elisp, The Emacs Lisp Reference Manual}). To set an environment
variable, use @samp{export @var{name}=@var{value}}. You can also use
@samp{set @var{variable} @var{value}}, which sets a Lisp variable if
@var{variable} is a symbol, or an environment variable if it's a
string (@pxref{Arguments}). Finally, you can temporarily set
environment variables for a single command with
@samp{@var{name}=@var{value} @var{command} @dots{}}. This is
equivalent to:
@example
@{
export @var{name}=@var{value}
@var{command} @dots{}
@}
@end example
@subsection Built-in variables
Eshell knows a few built-in variables:
@ -914,6 +942,16 @@ When using @code{$-}, you can also access older directories in the
directory ring via subscripting, e.g.@: @samp{$-[1]} refers to the
working directory @emph{before} the previous one.
@vindex $PATH
@item $PATH
This specifies the directories to search for executable programs. Its
value is a string, separated by @code{":"} for Unix and GNU systems,
and @code{";"} for MS systems. This variable is connection-aware, so
whenever you change the current directory to a different host
(@pxref{Remote Files, , , emacs, The GNU Emacs Manual}),
the value will automatically update to reflect the search path on that
host.
@vindex $_
@item $_
This refers to the last argument of the last command. With a
@ -1138,7 +1176,7 @@ a number if possible.
@item one or both (non-@code{nil}) lists
Concatenate ``adjacent'' elements of each value (possibly converting
back to a number as above). For example, @samp{$list("a" "b")c}
back to a number as above). For example, @samp{$(list "a" "b")c}
returns @samp{("a" "bc")}.
@item anything else

View file

@ -26911,10 +26911,17 @@ Gnus 5.10 on May 1st 2003 (24 releases).
On the January 4th 2004, No Gnus was begun.
Gnus 5.11 was bundled with GNU Emacs 22.1 in June 2007.
A version of No Gnus was released as Gnus 5.13 with GNU Emacs 23.1 in
July 2009.
On April 19, 2010 Gnus development was moved to Git.
On the January 31th 2012, Ma Gnus was begun.
Since then, Gnus has only been released together with Emacs.
If you happen upon a version of Gnus that has a prefixed name---``(ding)
Gnus'', ``September Gnus'', ``Red Gnus'', ``Quassia Gnus'',
``Pterodactyl Gnus'', ``Oort Gnus'', ``No Gnus'', ``Ma Gnus''---don't
@ -29080,8 +29087,9 @@ moving articles to a group that has not turned auto-expire on.
@subsubsection Ma Gnus
@cindex Ma Gnus
I'm sure there will be lots of text here. It's really spelled 真
Gnus.
It's really spelled 真Gnus. Ma Gnus was the code name for the
development version of Gnus started in 2012. These days, Gnus is only
released together with Emacs.
New features in Ma Gnus:
@ -29111,6 +29119,8 @@ The new hooks @code{gnus-gcc-pre-body-encode-hook} and
the message body of the Gcc copy of a sent message.
@xref{Archived Messages}.
For more recent changes, see the Emacs @file{NEWS} files.
@end itemize
@end itemize

View file

@ -356,6 +356,11 @@ previous 'C-x ='.
** Eshell
*** Eshell's PATH is now derived from 'exec-path'.
For consistency with remote connections, Eshell now uses 'exec-path'
to determine the execution path on the local system, instead of using
the PATH environment variable directly.
---
*** 'source' and '.' no longer accept the '--help' option.
This is for compatibility with the shell versions of these commands,
@ -815,22 +820,6 @@ This means Emacs built with GNUstep or built on macOS is now able to
display different faces and images inside tooltips when the
'use-system-tooltips' user option is nil.
** Connection-local variables
+++
*** Some connection-local variables are now user options.
The variables 'connection-local-profile-alist' and
'connection-local-criteria-alist' are now user options, in order to
make it more convenient to inspect and modify them.
+++
*** The default connection-local application can be changed temporarily.
Running 'with-connection-local-variables' defaults to application
'tramp'. This can be changed by let-binding
'connection-local-default-application' to another symbol. This is
useful when running code in a buffer where Tramp has already set some
connection-local variables.
---
** New minor mode 'pixel-scroll-precision-mode'.
When enabled, and if your mouse supports it, you can scroll the
@ -2621,7 +2610,7 @@ otherwise be returned.
*** Concatenating Eshell expansions now works more similarly to other shells.
When concatenating an Eshell expansion that returns a list, "adjacent"
elements of each operand are now concatenated together,
e.g. '$list("a" "b")c' returns '("a" "bc")'. See the "(eshell)
e.g. '$(list "a" "b")c' returns '("a" "bc")'. See the "(eshell)
Expansion" node in the Eshell manual for more details.
+++
@ -2868,8 +2857,8 @@ normal.
---
** Themes have special autoload cookies.
All build-in themes are scraped for ;;;###theme-autoload cookies that
are loaded along with the regular auto-loaded code.
All build-in themes are scraped for ';;;###theme-autoload' cookies
that are loaded along with the regular auto-loaded code.
+++
** 'buffer-modified-p' has been extended.
@ -3239,6 +3228,33 @@ TIMEOUT is the idle time after which to deactivate the transient map.
The default timeout value can be defined by the new variable
'set-transient-map-timeout'.
** Connection-local variables
+++
*** Some connection-local variables are now user options.
The variables 'connection-local-profile-alist' and
'connection-local-criteria-alist' are now user options, in order to
make it more convenient to inspect and modify them.
+++
*** New function 'connection-local-update-profile-variables'.
This function allows to modify the settings of an existing
connection-local profile.
+++
*** New macro 'with-connection-local-application-variables'.
This macro works like 'with-connection-local-variables', but it allows
to use another application but 'tramp'. This is useful when running
code in a buffer where Tramp has already set some connection-local
variables.
+++
*** New macro 'setq-connection-local'.
This allows dynamically setting variable values for a particular
connection within the body of 'with-connection-local-{application-}variables'.
See the "(elisp) Connection Local Variables" node in the Lisp
Reference manual for more information.
+++
** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'.
These function now take an optional comparison predicate argument.

View file

@ -125,13 +125,11 @@ and `shell-dirtrack-mode'."
;; Hyperlink handling (OSC 8)
(defvar ansi-osc-hyperlink-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-c\r" 'browse-url-button-open)
(define-key map [mouse-2] 'browse-url-button-open)
(define-key map [follow-link] 'mouse-face)
map)
"Keymap used by OSC 8 hyperlink buttons.")
(defvar-keymap ansi-osc-hyperlink-map
:doc "Keymap used by OSC 8 hyperlink buttons."
"C-c RET" #'browse-url-button-open
"<mouse-2>" #'browse-url-button-open
"<follow-link>" 'mouse-face)
(define-button-type 'ansi-osc-hyperlink
'keymap ansi-osc-hyperlink-map

View file

@ -481,6 +481,11 @@ convention was modified."
(puthash (indirect-function function) signature
advertised-signature-table))
(defun get-advertised-calling-convention (function)
"Get the advertised SIGNATURE of FUNCTION.
Return t if there isn't any."
(gethash function advertised-signature-table t))
(defun make-obsolete (obsolete-name current-name when)
"Make the byte-compiler warn that function OBSOLETE-NAME is obsolete.
OBSOLETE-NAME should be a function name or macro name (a symbol).

View file

@ -129,6 +129,7 @@
;; us from emitting warnings when compiling files which use cl-lib without
;; requiring it! (bug#30635)
(eval-when-compile (require 'cl-lib))
(eval-when-compile (require 'subr-x))
;; The feature of compiling in a specific target Emacs version
;; has been turned off because compile time options are a bad idea.
@ -1185,27 +1186,22 @@ message buffer `default-directory'."
(defun byte-compile--first-symbol-with-pos (form)
"Return the first symbol with position in form, or nil if none.
Order is by depth-first search."
(cond
((symbol-with-pos-p form) form)
((consp form)
(or (byte-compile--first-symbol-with-pos (car form))
(let ((sym nil))
(setq form (cdr form))
(while (and (consp form)
(not (setq sym (byte-compile--first-symbol-with-pos
(car form)))))
(setq form (cdr form)))
(or sym
(and form (byte-compile--first-symbol-with-pos form))))))
((or (vectorp form) (recordp form))
(let ((len (length form))
(i 0)
(sym nil))
(while (and (< i len)
(not (setq sym (byte-compile--first-symbol-with-pos
(aref form i)))))
(setq i (1+ i)))
sym))))
(named-let loop ((form form)
(depth 10)) ;Arbitrary limit.
(cond
((<= depth 0) nil) ;Avoid cycles (bug#58601).
((symbol-with-pos-p form) form)
((consp form)
(or (loop (car form) (1- depth))
(loop (cdr form) (1- depth))))
((or (vectorp form) (recordp form))
(let ((len (length form))
(i 0)
(sym nil))
(while (and (< i len)
(not (setq sym (loop (aref form i) (1- depth)))))
(setq i (1+ i)))
sym)))))
(defun byte-compile--warning-source-offset ()
"Return a source offset from `byte-compile-form-stack' or nil if none."
@ -1405,11 +1401,11 @@ when printing the error message."
(and (not macro-p)
(compiled-function-p (symbol-function fn)))))
(setq fn (symbol-function fn)))
(let ((advertised (gethash (if (and (symbolp fn) (fboundp fn))
;; Could be a subr.
(symbol-function fn)
fn)
advertised-signature-table t)))
(let ((advertised (get-advertised-calling-convention
(if (and (symbolp fn) (fboundp fn))
;; Could be a subr.
(symbol-function fn)
fn))))
(cond
((listp advertised)
(if macro-p
@ -2335,9 +2331,15 @@ With argument ARG, insert value in current buffer after the form."
(setq case-fold-search nil))
(displaying-byte-compile-warnings
(with-current-buffer inbuffer
(and byte-compile-current-file
(byte-compile-insert-header byte-compile-current-file
byte-compile--outbuffer))
(when byte-compile-current-file
(byte-compile-insert-header byte-compile-current-file
byte-compile--outbuffer)
;; Instruct native-comp to ignore this file.
(when (bound-and-true-p no-native-compile)
(with-current-buffer byte-compile--outbuffer
(insert
"(when (boundp 'comp--no-native-compile)
(puthash load-file-name t comp--no-native-compile))\n\n"))))
(goto-char (point-min))
;; Should we always do this? When calling multiple files, it
;; would be useful to delay this warning until all have been

View file

@ -650,13 +650,17 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
(cl--generic-name generic)
qualifiers specializers))
current-load-list :test #'equal)
(let (;; Prevent `defalias' from recording this as the definition site of
(let ((old-adv-cc (get-advertised-calling-convention
(symbol-function sym)))
;; Prevent `defalias' from recording this as the definition site of
;; the generic function.
current-load-list
;; BEWARE! Don't purify this function definition, since that leads
;; to memory corruption if the hash-tables it holds are modified
;; (the GC doesn't trace those pointers).
(purify-flag nil))
(when (listp old-adv-cc)
(set-advertised-calling-convention gfun old-adv-cc nil))
;; But do use `defalias', so that it interacts properly with nadvice,
;; e.g. for tracing/debug-on-entry.
(defalias sym gfun)))))

View file

@ -687,6 +687,9 @@ Useful to hook into pass checkers.")
'native-compiler-error)
(defvar comp-no-spawn nil
"Non-nil don't spawn native compilation processes.")
;; Moved early to avoid circularity when comp.el is loaded and
;; `macroexpand' needs to be advised (bug#47049).
;;;###autoload
@ -696,12 +699,9 @@ Useful to hook into pass checkers.")
(memq subr-name native-comp-never-optimize-functions)
(gethash subr-name comp-installed-trampolines-h))
(cl-assert (subr-primitive-p (symbol-function subr-name)))
(comp--install-trampoline
subr-name
(or (comp-trampoline-search subr-name)
(comp-trampoline-compile subr-name)
;; Should never happen.
(cl-assert nil)))))
(when-let ((trampoline (or (comp-trampoline-search subr-name)
(comp-trampoline-compile subr-name))))
(comp--install-trampoline subr-name trampoline))))
(cl-defstruct (comp-vec (:copier nil))
@ -3689,7 +3689,8 @@ Prepare every function for final compilation and drive the C back-end."
(print-circle t)
(print-escape-multibyte t)
(expr `((require 'comp)
(setf native-comp-verbose ,native-comp-verbose
(setf comp-no-spawn t
native-comp-verbose ,native-comp-verbose
comp-libgccjit-reproducer ,comp-libgccjit-reproducer
comp-ctxt ,comp-ctxt
native-comp-eln-load-path ',native-comp-eln-load-path
@ -3945,8 +3946,9 @@ display a message."
(file-newer-than-file-p
source-file (comp-el-to-eln-filename source-file))))
do (let* ((expr `((require 'comp)
(setq comp-async-compilation t)
(setq warning-fill-column most-positive-fixnum)
(setq comp-async-compilation t
comp-no-spawn t
warning-fill-column most-positive-fixnum)
,(let ((set (list 'setq)))
(dolist (var '(comp-file-preloaded-p
native-compile-target-directory
@ -4046,72 +4048,73 @@ the deferred compilation mechanism."
(stringp function-or-file))
(signal 'native-compiler-error
(list "Not a function symbol or file" function-or-file)))
(catch 'no-native-compile
(let* ((print-symbols-bare t)
(data function-or-file)
(comp-native-compiling t)
(byte-native-qualities nil)
(symbols-with-pos-enabled t)
;; Have byte compiler signal an error when compilation fails.
(byte-compile-debug t)
(comp-ctxt (make-comp-ctxt :output output
:with-late-load with-late-load)))
(comp-log "\n \n" 1)
(unwind-protect
(progn
(condition-case err
(cl-loop
with report = nil
for t0 = (current-time)
for pass in comp-passes
unless (memq pass comp-disabled-passes)
do
(comp-log (format "(%s) Running pass %s:\n"
function-or-file pass)
2)
(setf data (funcall pass data))
(push (cons pass (float-time (time-since t0))) report)
(cl-loop for f in (alist-get pass comp-post-pass-hooks)
do (funcall f data))
finally
(when comp-log-time-report
(comp-log (format "Done compiling %s" data) 0)
(cl-loop for (pass . time) in (reverse report)
do (comp-log (format "Pass %s took: %fs."
pass time) 0))))
(native-compiler-skip)
(t
(let ((err-val (cdr err)))
;; If we are doing an async native compilation print the
;; error in the correct format so is parsable and abort.
(if (and comp-async-compilation
(not (eq (car err) 'native-compiler-error)))
(progn
(message (if err-val
"%s: Error: %s %s"
"%s: Error %s")
function-or-file
(get (car err) 'error-message)
(car-safe err-val))
(kill-emacs -1))
;; Otherwise re-signal it adding the compilation input.
(signal (car err) (if (consp err-val)
(cons function-or-file err-val)
(list function-or-file err-val)))))))
(if (stringp function-or-file)
data
;; So we return the compiled function.
(native-elisp-load data)))
;; We may have created a temporary file when we're being
;; called with something other than a file as the argument.
;; Delete it.
(when (and (not (stringp function-or-file))
(not output)
comp-ctxt
(comp-ctxt-output comp-ctxt)
(file-exists-p (comp-ctxt-output comp-ctxt)))
(message "Deleting %s" (comp-ctxt-output comp-ctxt))
(delete-file (comp-ctxt-output comp-ctxt)))))))
(unless comp-no-spawn
(catch 'no-native-compile
(let* ((print-symbols-bare t)
(data function-or-file)
(comp-native-compiling t)
(byte-native-qualities nil)
(symbols-with-pos-enabled t)
;; Have byte compiler signal an error when compilation fails.
(byte-compile-debug t)
(comp-ctxt (make-comp-ctxt :output output
:with-late-load with-late-load)))
(comp-log "\n \n" 1)
(unwind-protect
(progn
(condition-case err
(cl-loop
with report = nil
for t0 = (current-time)
for pass in comp-passes
unless (memq pass comp-disabled-passes)
do
(comp-log (format "(%s) Running pass %s:\n"
function-or-file pass)
2)
(setf data (funcall pass data))
(push (cons pass (float-time (time-since t0))) report)
(cl-loop for f in (alist-get pass comp-post-pass-hooks)
do (funcall f data))
finally
(when comp-log-time-report
(comp-log (format "Done compiling %s" data) 0)
(cl-loop for (pass . time) in (reverse report)
do (comp-log (format "Pass %s took: %fs."
pass time) 0))))
(native-compiler-skip)
(t
(let ((err-val (cdr err)))
;; If we are doing an async native compilation print the
;; error in the correct format so is parsable and abort.
(if (and comp-async-compilation
(not (eq (car err) 'native-compiler-error)))
(progn
(message (if err-val
"%s: Error: %s %s"
"%s: Error %s")
function-or-file
(get (car err) 'error-message)
(car-safe err-val))
(kill-emacs -1))
;; Otherwise re-signal it adding the compilation input.
(signal (car err) (if (consp err-val)
(cons function-or-file err-val)
(list function-or-file err-val)))))))
(if (stringp function-or-file)
data
;; So we return the compiled function.
(native-elisp-load data)))
;; We may have created a temporary file when we're being
;; called with something other than a file as the argument.
;; Delete it.
(when (and (not (stringp function-or-file))
(not output)
comp-ctxt
(comp-ctxt-output comp-ctxt)
(file-exists-p (comp-ctxt-output comp-ctxt)))
(message "Deleting %s" (comp-ctxt-output comp-ctxt))
(delete-file (comp-ctxt-output comp-ctxt))))))))
(defun native-compile-async-skip-p (file load selector)
"Return non-nil if FILE's compilation should be skipped.
@ -4119,6 +4122,7 @@ the deferred compilation mechanism."
LOAD and SELECTOR work as described in `native--compile-async'."
;; Make sure we are not already compiling `file' (bug#40838).
(or (gethash file comp-async-compilations)
(gethash (file-name-with-extension file "elc") comp--no-native-compile)
(cond
((null selector) nil)
((functionp selector) (not (funcall selector file)))
@ -4166,7 +4170,8 @@ bytecode definition was not changed in the meantime)."
(error "LOAD must be nil, t or 'late"))
(unless (listp files)
(setf files (list files)))
(let (file-list)
(let ((added-something nil)
file-list)
(dolist (file-or-dir files)
(cond ((file-directory-p file-or-dir)
(dolist (file (if recursively
@ -4194,11 +4199,15 @@ bytecode definition was not changed in the meantime)."
(make-directory out-dir t))
(if (file-writable-p out-filename)
(setf comp-files-queue
(append comp-files-queue `((,file . ,load))))
(append comp-files-queue `((,file . ,load)))
added-something t)
(display-warning 'comp
(format "No write access for %s skipping."
out-filename)))))))
(when (zerop (comp-async-runnings))
;; Perhaps nothing passed `native-compile-async-skip-p'?
(when (and added-something
;; Don't start if there's one already running.
(zerop (comp-async-runnings)))
(comp-run-async-workers))))
@ -4234,14 +4243,13 @@ Search happens in `native-comp-eln-load-path'."
(defun native-compile (function-or-file &optional output)
"Compile FUNCTION-OR-FILE into native code.
This is the synchronous entry-point for the Emacs Lisp native
compiler.
FUNCTION-OR-FILE is a function symbol, a form, or the filename of
an Emacs Lisp source file.
If OUTPUT is non-nil, use it as the filename for the compiled
object.
If FUNCTION-OR-FILE is a filename, return the filename of the
compiled object. If FUNCTION-OR-FILE is a function symbol or a
form, return the compiled function."
compiler. FUNCTION-OR-FILE is a function symbol, a form, or the
filename of an Emacs Lisp source file. If OUTPUT is non-nil, use
it as the filename for the compiled object. If FUNCTION-OR-FILE
is a filename, if the compilation was successful return the
filename of the compiled object. If FUNCTION-OR-FILE is a
function symbol or a form, if the compilation was successful
return the compiled function."
(comp--native-compile function-or-file nil output))
;;;###autoload
@ -4328,13 +4336,15 @@ of (commands) to run simultaneously."
;; `invocation-directory'.
(setq dir (expand-file-name dir invocation-directory))
(when (file-exists-p dir)
(dolist (subdir (directory-files dir t))
(dolist (subdir (seq-filter
(lambda (f) (not (string-match (rx "/." (? ".") eos) f)))
(directory-files dir t)))
(when (and (file-directory-p subdir)
(file-writable-p subdir)
(not (equal (file-name-nondirectory
(directory-file-name subdir))
comp-native-version-dir)))
(message "Deleting %s..." subdir)
(message "Deleting `%s'..." subdir)
;; We're being overly cautious here -- there shouldn't be
;; anything but .eln files in these directories.
(dolist (eln (directory-files subdir t "\\.eln\\(\\.tmp\\)?\\'"))

View file

@ -738,12 +738,12 @@ rules for built-in packages and excluded files."
(expand-file-name "emacs-lisp/loaddefs-gen.el" lisp-directory)
output-file)))
(let ((lisp-mode-autoload-regexp
"^;;;###\\(\\(noexist\\)-\\)?\\(theme-autoload\\)"))
"^;;;###\\(\\(noexist\\)-\\)?\\(theme-autoload\\)"))
(loaddefs-generate
(expand-file-name "../etc/themes/" lisp-directory)
(expand-file-name "theme-loaddefs.el" lisp-directory))))
;;;###autoload (load "theme-loaddefs.el")
;;;###autoload (load "theme-loaddefs.el" t)
(provide 'loaddefs-gen)

View file

@ -261,9 +261,9 @@ the command."
(defcustom eshell-subcommand-bindings
'((eshell-in-subcommand-p t)
(eshell-in-pipeline-p nil)
(default-directory default-directory)
(process-environment (eshell-copy-environment)))
(default-directory default-directory))
"A list of `let' bindings for subcommand environments."
:version "29.1" ; removed `process-environment'
:type 'sexp
:risky t)
@ -1274,8 +1274,9 @@ be finished later after the completion of an asynchronous subprocess."
name)
(eshell-search-path name)))))
(if (not program)
(eshell-error (format "which: no %s in (%s)\n"
name (getenv "PATH")))
(eshell-error (format "which: no %s in (%s)\n"
name (string-join (eshell-get-path t)
(path-separator))))
(eshell-printn program)))))
(put 'eshell/which 'eshell-no-numeric-conversions t)

View file

@ -77,7 +77,7 @@ but Eshell will be able to understand
(let ((list (eshell-get-path))
suffixes n1 n2 file)
(while list
(setq n1 (concat (car list) name))
(setq n1 (file-name-concat (car list) name))
(setq suffixes eshell-binary-suffixes)
(while suffixes
(setq n2 (concat n1 (car suffixes)))
@ -239,17 +239,16 @@ causing the user to wonder if anything's really going on..."
(?h "help" nil nil "display this usage message")
:usage "[-b] PATH
Adds the given PATH to $PATH.")
(if args
(progn
(setq eshell-path-env (getenv "PATH")
args (mapconcat #'identity args path-separator)
eshell-path-env
(if prepend
(concat args path-separator eshell-path-env)
(concat eshell-path-env path-separator args)))
(setenv "PATH" eshell-path-env))
(dolist (dir (parse-colon-path (getenv "PATH")))
(eshell-printn dir)))))
(let ((path (eshell-get-path t)))
(if args
(progn
(setq path (if prepend
(append args path)
(append path args)))
(eshell-set-path path)
(string-join path (path-separator)))
(dolist (dir path)
(eshell-printn dir))))))
(put 'eshell/addpath 'eshell-no-numeric-conversions t)
(put 'eshell/addpath 'eshell-filename-arguments t)

View file

@ -249,17 +249,60 @@ trailing newlines removed. Otherwise, this behaves as follows:
It might be different from \(getenv \"PATH\"), when
`default-directory' points to a remote host.")
(defun eshell-get-path ()
(make-obsolete-variable 'eshell-path-env 'eshell-get-path "29.1")
(defvar-local eshell-path-env-list nil)
(connection-local-set-profile-variables
'eshell-connection-default-profile
'((eshell-path-env-list . nil)))
(connection-local-set-profiles
'(:application eshell)
'eshell-connection-default-profile)
(defun eshell-get-path (&optional literal-p)
"Return $PATH as a list.
Add the current directory on MS-Windows."
(eshell-parse-colon-path
(if (eshell-under-windows-p)
(concat "." path-separator eshell-path-env)
eshell-path-env)))
If LITERAL-P is nil, return each directory of the path as a full,
possibly-remote file name; on MS-Windows, add the current
directory as the first directory in the path as well.
If LITERAL-P is non-nil, return the local part of each directory,
as the $PATH was actually specified."
(with-connection-local-application-variables 'eshell
(let ((remote (file-remote-p default-directory))
(path
(or eshell-path-env-list
;; If not already cached, get the path from
;; `exec-path', removing the last element, which is
;; `exec-directory'.
(setq-connection-local eshell-path-env-list
(butlast (exec-path))))))
(when (and (not literal-p)
(not remote)
(eshell-under-windows-p))
(push "." path))
(if (and remote (not literal-p))
(mapcar (lambda (x) (file-name-concat remote x)) path)
path))))
(defun eshell-set-path (path)
"Set the Eshell $PATH to PATH.
PATH can be either a list of directories or a string of
directories separated by `path-separator'."
(with-connection-local-application-variables 'eshell
(setq-connection-local
eshell-path-env-list
(if (listp path)
path
;; Don't use `parse-colon-path' here, since we don't want
;; the additonal translations it does on each element.
(split-string path (path-separator))))))
(defun eshell-parse-colon-path (path-env)
"Split string with `parse-colon-path'.
Prepend remote identification of `default-directory', if any."
(declare (obsolete nil "29.1"))
(let ((remote (file-remote-p default-directory)))
(if remote
(mapcar

View file

@ -113,7 +113,7 @@
(require 'pcomplete)
(require 'ring)
(defconst eshell-inside-emacs (format "%s,eshell" emacs-version)
(defvar-local eshell-inside-emacs (format "%s,eshell" emacs-version)
"Value for the `INSIDE_EMACS' environment variable.")
(defgroup eshell-var nil
@ -156,14 +156,21 @@ if they are quoted with a backslash."
("LINES" ,(lambda () (window-body-height nil 'remap)) t t)
("INSIDE_EMACS" eshell-inside-emacs t)
;; for eshell-cmd.el
;; for esh-ext.el
("PATH" (,(lambda () (string-join (eshell-get-path t) (path-separator)))
. ,(lambda (_ value)
(eshell-set-path value)
value))
t t)
;; for esh-cmd.el
("_" ,(lambda (indices quoted)
(if (not indices)
(car (last eshell-last-arguments))
(eshell-apply-indices eshell-last-arguments
indices quoted))))
("?" eshell-last-command-status)
("$" eshell-last-command-result)
("?" (eshell-last-command-status . nil))
("$" (eshell-last-command-result . nil))
;; for em-alias.el and em-script.el
("0" eshell-command-name)
@ -176,7 +183,7 @@ if they are quoted with a backslash."
("7" ,(lambda () (nth 6 eshell-command-arguments)) nil t)
("8" ,(lambda () (nth 7 eshell-command-arguments)) nil t)
("9" ,(lambda () (nth 8 eshell-command-arguments)) nil t)
("*" eshell-command-arguments))
("*" (eshell-command-arguments . nil)))
"This list provides aliasing for variable references.
Each member is of the following form:
@ -186,6 +193,11 @@ NAME defines the name of the variable, VALUE is a Lisp value used to
compute the string value that will be returned when the variable is
accessed via the syntax `$NAME'.
If VALUE is a cons (GET . SET), then variable references to NAME
will use GET to get the value, and SET to set it. GET and SET
can be one of the forms described below. If SET is nil, the
variable is read-only.
If VALUE is a function, its behavior depends on the value of
SIMPLE-FUNCTION. If SIMPLE-FUNCTION is nil, call VALUE with two
arguments: the list of the indices that were used in the reference,
@ -193,23 +205,30 @@ and either t or nil depending on whether or not the variable was
quoted with double quotes. For example, if `NAME' were aliased
to a function, a reference of `$NAME[10][20]' would result in that
function being called with the arguments `((\"10\") (\"20\"))' and
nil.
If SIMPLE-FUNCTION is non-nil, call the function with no arguments
and then pass its return value to `eshell-apply-indices'.
nil. If SIMPLE-FUNCTION is non-nil, call the function with no
arguments and then pass its return value to `eshell-apply-indices'.
If VALUE is a string, return the value for the variable with that
name in the current environment. If no variable with that name exists
in the environment, but if a symbol with that same name exists and has
a value bound to it, return that symbol's value instead. You can
prefer symbol values over environment values by setting the value
of `eshell-prefer-lisp-variables' to t.
When VALUE is a function, it's read-only by default. To make it
writeable, use the (GET . SET) form described above. If SET is a
function, it takes two arguments: a list of indices (currently
always nil, but reserved for future enhancement), and the new
value to set.
If VALUE is a symbol, return the value bound to it.
If VALUE is a string, get/set the value for the variable with
that name in the current environment. When getting the value, if
no variable with that name exists in the environment, but if a
symbol with that same name exists and has a value bound to it,
return that symbol's value instead. You can prefer symbol values
over environment values by setting the value of
`eshell-prefer-lisp-variables' to t.
If VALUE is a symbol, get/set the value bound to it.
If VALUE has any other type, signal an error.
Additionally, if COPY-TO-ENVIRONMENT is non-nil, the alias should be
copied (a.k.a. \"exported\") to the environment of created subprocesses."
:version "29.1"
:type '(repeat (list string sexp
(choice (const :tag "Copy to environment" t)
(const :tag "Use only in Eshell" nil))
@ -234,6 +253,12 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
;; changing a variable will affect all of Emacs.
(unless eshell-modify-global-environment
(setq-local process-environment (eshell-copy-environment)))
(setq-local eshell-subcommand-bindings
(append
'((process-environment (eshell-copy-environment))
(eshell-variable-aliases-list eshell-variable-aliases-list)
(eshell-path-env-list eshell-path-env-list))
eshell-subcommand-bindings))
(setq-local eshell-special-chars-inside-quoting
(append eshell-special-chars-inside-quoting '(?$)))
@ -282,9 +307,9 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
(while (string-match setvar command)
(nconc
l (list
(list 'setenv (match-string 1 command)
(match-string 2 command)
(= (length (match-string 2 command)) 0))))
(list 'eshell-set-variable
(match-string 1 command)
(match-string 2 command))))
(setq command (eshell-stringify (car args))
args (cdr args)))
(cdr l))
@ -302,6 +327,11 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
(defun eshell/define (var-alias definition)
"Define a VAR-ALIAS using DEFINITION."
;; FIXME: This function doesn't work (it produces variable aliases
;; in a form not recognized by other parts of the code), and likely
;; hasn't worked since before its introduction into Emacs. It
;; should either be removed or fixed up.
(declare (obsolete nil "29.1"))
(if (not definition)
(setq eshell-variable-aliases-list
(delq (assoc var-alias eshell-variable-aliases-list)
@ -323,12 +353,11 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
(defun eshell/export (&rest sets)
"This alias allows the `export' command to act as bash users expect."
(while sets
(if (and (stringp (car sets))
(string-match "^\\([^=]+\\)=\\(.*\\)" (car sets)))
(setenv (match-string 1 (car sets))
(match-string 2 (car sets))))
(setq sets (cdr sets))))
(dolist (set sets)
(when (and (stringp set)
(string-match "^\\([^=]+\\)=\\(.*\\)" set))
(eshell-set-variable (match-string 1 set)
(match-string 2 set)))))
(defun pcomplete/eshell-mode/export ()
"Completion function for Eshell's `export'."
@ -338,16 +367,28 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
(eshell-envvar-names)))))
(defun eshell/unset (&rest args)
"Unset an environment variable."
(while args
(if (stringp (car args))
(setenv (car args) nil t))
(setq args (cdr args))))
"Unset one or more variables.
This is equivalent to calling `eshell/set' for all of ARGS with
the values of nil for each."
(dolist (arg args)
(eshell-set-variable arg nil)))
(defun pcomplete/eshell-mode/unset ()
"Completion function for Eshell's `unset'."
(while (pcomplete-here (eshell-envvar-names))))
(defun eshell/set (&rest args)
"Allow command-ish use of `set'."
(let (last-value)
(while args
(setq last-value (eshell-set-variable (car args) (cadr args))
args (cddr args)))
last-value))
(defun pcomplete/eshell-mode/set ()
"Completion function for Eshell's `set'."
(while (pcomplete-here (eshell-envvar-names))))
(defun eshell/setq (&rest args)
"Allow command-ish use of `setq'."
(let (last-value)
@ -561,18 +602,21 @@ INDICES is a list of index-lists (see `eshell-parse-indices').
If QUOTED is non-nil, this was invoked inside double-quotes."
(if-let ((alias (assoc name eshell-variable-aliases-list)))
(let ((target (nth 1 alias)))
(when (and (not (functionp target))
(consp target))
(setq target (car target)))
(cond
((functionp target)
(if (nth 3 alias)
(eshell-apply-indices (funcall target) indices quoted)
(condition-case nil
(funcall target indices quoted)
(wrong-number-of-arguments
(display-warning
:warning (concat "Function for `eshell-variable-aliases-list' "
"entry should accept two arguments: INDICES "
"and QUOTED.'"))
(funcall target indices)))))
(let ((max-arity (cdr (func-arity target))))
(if (or (eq max-arity 'many) (>= max-arity 2))
(funcall target indices quoted)
(display-warning
:warning (concat "Function for `eshell-variable-aliases-list' "
"entry should accept two arguments: INDICES "
"and QUOTED.'"))
(funcall target indices)))))
((symbolp target)
(eshell-apply-indices (symbol-value target) indices quoted))
(t
@ -589,6 +633,44 @@ If QUOTED is non-nil, this was invoked inside double-quotes."
(getenv name)))
indices quoted)))
(defun eshell-set-variable (name value)
"Set the variable named NAME to VALUE.
NAME can be a string (in which case it refers to an environment
variable or variable alias) or a symbol (in which case it refers
to a Lisp variable)."
(if-let ((alias (assoc name eshell-variable-aliases-list)))
(let ((target (nth 1 alias)))
(cond
((functionp target)
(setq target nil))
((consp target)
(setq target (cdr target))))
(cond
((functionp target)
(funcall target nil value))
((null target)
(unless eshell-in-subcommand-p
(error "Variable `%s' is not settable" (eshell-stringify name)))
(push `(,name ,(lambda () value) t t)
eshell-variable-aliases-list)
value)
;; Since getting a variable alias with a string target and
;; `eshell-prefer-lisp-variables' non-nil gets the
;; corresponding Lisp variable, make sure setting does the
;; same.
((and eshell-prefer-lisp-variables
(stringp target))
(eshell-set-variable (intern target) value))
(t
(eshell-set-variable target value))))
(cond
((stringp name)
(setenv name value))
((symbolp name)
(set name value))
(t
(error "Unknown variable `%s'" (eshell-stringify name))))))
(defun eshell-apply-indices (value indices &optional quoted)
"Apply to VALUE all of the given INDICES, returning the sub-result.
The format of INDICES is:

View file

@ -620,6 +620,18 @@ PROFILES is a list of connection profiles (symbols)."
:group 'tramp
:version "29.1")
(defvar connection-local-criteria nil
"The current connection-local criteria, or nil.
This is set while executing the body of
`with-connection-local-variables'.")
(defvar connection-local-profile-name-for-setq nil
"The current connection-local profile name, or nil.
This is the name of the profile to use when setting variables via
`setq-connection-local'. Its value is derived from
`connection-local-criteria' and is set while executing the body
of `with-connection-local-variables'.")
(defsubst connection-local-normalize-criteria (criteria)
"Normalize plist CRITERIA according to properties.
Return a reordered plist."
@ -696,6 +708,23 @@ in order."
(customize-set-variable
'connection-local-profile-alist connection-local-profile-alist))
;;;###autoload
(defun connection-local-update-profile-variables (profile variables)
"Update the variable settings for PROFILE in-place.
VARIABLES is a list that declares connection-local variables for
the connection profile. An element in VARIABLES is an alist
whose elements are of the form (VAR . VALUE).
Unlike `connection-local-set-profile-variables' (which see), this
function preserves the values of any existing variable
definitions that aren't listed in VARIABLES."
(when-let ((existing-variables
(nreverse (connection-local-get-profile-variables profile))))
(dolist (var variables)
(setf (alist-get (car var) existing-variables) (cdr var)))
(setq variables (nreverse existing-variables)))
(connection-local-set-profile-variables profile variables))
(defun hack-connection-local-variables (criteria)
"Read connection-local variables according to CRITERIA.
Store the connection-local variables in buffer local
@ -738,6 +767,15 @@ If APPLICATION is nil, `connection-local-default-application' is used."
:user ,(file-remote-p default-directory 'user)
:machine ,(file-remote-p default-directory 'host))))
(defun connection-local-profile-name-for-criteria (criteria)
"Get a connection-local profile name based on CRITERIA."
(when criteria
(let (print-level print-length)
(intern (concat
"autogenerated-connection-local-profile/"
(prin1-to-string
(connection-local-normalize-criteria criteria)))))))
;;;###autoload
(defmacro with-connection-local-variables (&rest body)
"Apply connection-local variables according to `default-directory'.
@ -745,16 +783,28 @@ Execute BODY, and unwind connection-local variables."
(declare (debug t))
`(with-connection-local-variables-1 (lambda () ,@body)))
;;;###autoload
(defmacro with-connection-local-application-variables (application &rest body)
"Apply connection-local variables for APPLICATION in `default-directory'.
Execute BODY, and unwind connection-local variables."
(declare (debug t) (indent 1))
`(let ((connection-local-default-application ,application))
(with-connection-local-variables-1 (lambda () ,@body))))
;;;###autoload
(defun with-connection-local-variables-1 (body-fun)
"Apply connection-local variables according to `default-directory'.
Call BODY-FUN with no args, and then unwind connection-local variables."
(if (file-remote-p default-directory)
(let ((enable-connection-local-variables t)
(old-buffer-local-variables (buffer-local-variables))
connection-local-variables-alist)
(hack-connection-local-variables-apply
(connection-local-criteria-for-default-directory))
(let* ((enable-connection-local-variables t)
(connection-local-criteria
(connection-local-criteria-for-default-directory))
(connection-local-profile-name-for-setq
(connection-local-profile-name-for-criteria
connection-local-criteria))
(old-buffer-local-variables (buffer-local-variables))
connection-local-variables-alist)
(hack-connection-local-variables-apply connection-local-criteria)
(unwind-protect
(funcall body-fun)
;; Cleanup.
@ -766,6 +816,49 @@ Call BODY-FUN with no args, and then unwind connection-local variables."
;; No connection-local variables to apply.
(funcall body-fun)))
;;;###autoload
(defmacro setq-connection-local (&rest pairs)
"Set each VARIABLE connection-locally to VALUE.
When `connection-local-profile-name-for-setq' is set, assign each
variable's value on that connection profile, and set that profile
for `connection-local-criteria'. You can use this in combination
with `with-connection-local-variables', as in
(with-connection-local-variables
(setq-connection-local VARIABLE VALUE))
If there's no connection-local profile to use, just set the
variables normally, as with `setq'.
The variables are literal symbols and should not be quoted. The
second VALUE is not computed until after the first VARIABLE is
set, and so on; each VALUE can use the new value of variables set
earlier in the `setq-connection-local'. The return value of the
`setq-connection-local' form is the value of the last VALUE.
\(fn [VARIABLE VALUE]...)"
(declare (debug setq))
(unless (zerop (mod (length pairs) 2))
(error "PAIRS must have an even number of variable/value members"))
(let ((set-expr nil)
(profile-vars nil))
(while pairs
(unless (symbolp (car pairs))
(error "Attempting to set a non-symbol: %s" (car pairs)))
(push `(set ',(car pairs) ,(cadr pairs)) set-expr)
(push `(cons ',(car pairs) ,(car pairs)) profile-vars)
(setq pairs (cddr pairs)))
`(prog1
,(macroexp-progn (nreverse set-expr))
(when connection-local-profile-name-for-setq
(connection-local-update-profile-variables
connection-local-profile-name-for-setq
(list ,@(nreverse profile-vars)))
(connection-local-set-profiles
connection-local-criteria
connection-local-profile-name-for-setq)))))
;;;###autoload
(defun path-separator ()
"The connection-local value of `path-separator'."

View file

@ -5192,10 +5192,7 @@ command evaluates `message-send-mail-hook' just before sending a message."
(defun message-canlock-generate ()
"Return a string that is non-trivial to guess.
Do not use this for anything important, it is cryptographically weak."
(sha1 (concat (message-unique-id)
(format "%x%x%x" (random) (random) (random))
(prin1-to-string (recent-keys))
(prin1-to-string (garbage-collect)))))
(secure-hash 'sha1 'iv-auto 128))
(defvar canlock-password)
(defvar canlock-password-for-verify)

View file

@ -669,7 +669,7 @@ the C sources, too."
"Insert usage at point and return docstring. With highlighting."
(if (keymapp function)
doc ; If definition is a keymap, skip arglist note.
(let* ((advertised (gethash real-def advertised-signature-table t))
(let* ((advertised (get-advertised-calling-convention real-def))
(arglist (if (listp advertised)
advertised (help-function-arglist real-def)))
(usage (help-split-fundoc doc function)))

View file

@ -147,16 +147,16 @@ and then returns."
(while (or (memq char (append help-event-list
(cons help-char '( ?? ?\C-v ?\s ?\177 ?\M-v ?\S-\s
deletechar backspace vertical-scroll-bar
next prior up down))))
home end next prior up down))))
(eq (car-safe char) 'switch-frame)
(equal key "\M-v"))
(condition-case nil
(cond
((eq (car-safe char) 'switch-frame)
(handle-switch-frame char))
((memq char '(?\C-v ?\s next))
((memq char '(?\C-v ?\s next end))
(scroll-up))
((or (memq char '(?\177 ?\M-v ?\S-\s deletechar backspace prior))
((or (memq char '(?\177 ?\M-v ?\S-\s deletechar backspace prior home))
(equal key "\M-v"))
(scroll-down))
((memq char '(down))
@ -210,7 +210,11 @@ and then returns."
(unless (eq new-frame (selected-frame))
(iconify-frame new-frame))
(setq new-frame nil)))
(ding)))))
(unless (equal (key-description key) "C-g")
(message (substitute-command-keys
(format "No help command is bound to `\\`%s''"
(key-description key))))
(ding))))))
(when config
(set-window-configuration config))
(when new-frame

View file

@ -259,7 +259,10 @@ buffer.")
;; help command loop.
(help-quit))
((and-let* ((window (get-buffer-window "*Quick Help*")))
(quit-window t window)))
(quit-window t window)
;; Clear the message we may have gotten from `C-h' and then
;; waiting before hitting `q'.
(message "")))
((help-quick))))
(defvar help-return-method nil
@ -741,7 +744,8 @@ or a buffer name."
(setq-local outline-heading-end-regexp ":\n")
(setq-local outline-level (lambda () 1))
(setq-local outline-minor-mode-cycle t
outline-minor-mode-highlight t)
outline-minor-mode-highlight t
outline-minor-mode-insert-buttons t)
(outline-minor-mode 1)
(save-excursion
(goto-char (point-min))

View file

@ -4702,14 +4702,13 @@ Search happens in `native-comp-eln-load-path'.
(autoload 'native-compile "comp" "\
Compile FUNCTION-OR-FILE into native code.
This is the synchronous entry-point for the Emacs Lisp native
compiler.
FUNCTION-OR-FILE is a function symbol, a form, or the filename of
an Emacs Lisp source file.
If OUTPUT is non-nil, use it as the filename for the compiled
object.
If FUNCTION-OR-FILE is a filename, return the filename of the
compiled object. If FUNCTION-OR-FILE is a function symbol or a
form, return the compiled function.
compiler. FUNCTION-OR-FILE is a function symbol, a form, or the
filename of an Emacs Lisp source file. If OUTPUT is non-nil, use
it as the filename for the compiled object. If FUNCTION-OR-FILE
is a filename, if the compilation was successful return the
filename of the compiled object. If FUNCTION-OR-FILE is a
function symbol or a form, if the compilation was successful
return the compiled function.
(fn FUNCTION-OR-FILE &optional OUTPUT)")
(autoload 'batch-native-compile "comp" "\
@ -4960,8 +4959,6 @@ evaluate `compilation-shell-minor-mode'.
The mode's hook is called both when the mode is enabled and when
it is disabled.
\\{compilation-shell-minor-mode-map}
(fn &optional ARG)" t)
(autoload 'compilation-minor-mode "compile" "\
Toggle Compilation minor mode.
@ -4985,8 +4982,6 @@ evaluate `compilation-minor-mode'.
The mode's hook is called both when the mode is enabled and when
it is disabled.
\\{compilation-minor-mode-map}
(fn &optional ARG)" t)
(autoload 'compilation-next-error-function "compile" "\
Advance to the next error message and visit the file where the error was.
@ -8371,7 +8366,7 @@ A second call of this function without changing point inserts the next match.
A call with prefix PREFIX reads the symbol to insert from the minibuffer with
completion.
(fn PREFIX)" t)
(fn PREFIX)" '("P"))
(autoload 'ebrowse-tags-loop-continue "ebrowse" "\
Repeat last operation on files in tree.
FIRST-TIME non-nil means this is not a repetition, but the first time.
@ -9920,7 +9915,7 @@ When present, ID should be an opaque object used to identify the
connection unequivocally. This is rarely needed and not available
interactively.
(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) ID)" t)
(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) ID)" '((erc-select-read-args)))
(defalias 'erc-select #'erc)
(autoload 'erc-tls "erc" "\
ERC is a powerful, modular, and extensible IRC client.
@ -9967,7 +9962,7 @@ symbol composed of letters from the Latin alphabet.) This option is
generally unneeded, however. See info node `(erc) Connecting' for use
cases. Not available interactively.
(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE ID)" t)
(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE ID)" '((let ((erc-default-port erc-default-port-tls)) (erc-select-read-args))))
(autoload 'erc-handle-irc-url "erc" "\
Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD.
If ERC is already connected to HOST:PORT, simply /join CHANNEL.
@ -10183,9 +10178,7 @@ it has to be wrapped in `(eval (quote ...))'.
If NAME is already defined as a test and Emacs is running
in batch mode, an error is signalled.
(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil t)
(function-put 'ert-deftest 'doc-string-elt 3)
(function-put 'ert-deftest 'lisp-indent-function 2)
(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil 'macro)
(autoload 'ert-run-tests-batch "ert" "\
Run the tests specified by SELECTOR, printing results to the terminal.
@ -11719,6 +11712,17 @@ variables are set in the server's process buffer according to the
VARIABLES list of the connection profile. The list is processed
in order.
(fn PROFILE VARIABLES)")
(autoload 'connection-local-update-profile-variables "files-x" "\
Update the variable settings for PROFILE in-place.
VARIABLES is a list that declares connection-local variables for
the connection profile. An element in VARIABLES is an alist
whose elements are of the form (VAR . VALUE).
Unlike `connection-local-set-profile-variables' (which see), this
function preserves the values of any existing variable
definitions that aren't listed in VARIABLES.
(fn PROFILE VARIABLES)")
(autoload 'hack-connection-local-variables-apply "files-x" "\
Apply connection-local variables identified by CRITERIA.
@ -11731,11 +11735,38 @@ Apply connection-local variables according to `default-directory'.
Execute BODY, and unwind connection-local variables.
(fn &rest BODY)" nil t)
(autoload 'with-connection-local-application-variables "files-x" "\
Apply connection-local variables for APPLICATION in `default-directory'.
Execute BODY, and unwind connection-local variables.
(fn APPLICATION &rest BODY)" nil t)
(function-put 'with-connection-local-application-variables 'lisp-indent-function 1)
(autoload 'with-connection-local-variables-1 "files-x" "\
Apply connection-local variables according to `default-directory'.
Call BODY-FUN with no args, and then unwind connection-local variables.
(fn BODY-FUN)")
(autoload 'setq-connection-local "files-x" "\
Set each VARIABLE connection-locally to VALUE.
When `connection-local-profile-name-for-setq' is set, assign each
variable's value on that connection profile, and set that profile
for `connection-local-criteria'. You can use this in combination
with `with-connection-local-variables', as in
(with-connection-local-variables
(setq-connection-local VARIABLE VALUE))
If there's no connection-local profile to use, just set the
variables normally, as with `setq'.
The variables are literal symbols and should not be quoted. The
second VALUE is not computed until after the first VARIABLE is
set, and so on; each VALUE can use the new value of variables set
earlier in the `setq-connection-local'. The return value of the
`setq-connection-local' form is the value of the last VALUE.
(fn [VARIABLE VALUE]...)" nil t)
(autoload 'path-separator "files-x" "\
The connection-local value of `path-separator'.")
(autoload 'null-device "files-x" "\
@ -12261,8 +12292,6 @@ evaluate `flymake-mode'.
The mode's hook is called both when the mode is enabled and when
it is disabled.
\\{flymake-mode-map}
(fn &optional ARG)" t)
(autoload 'flymake-mode-on "flymake" "\
Turn Flymake mode on.")
@ -15888,8 +15917,7 @@ inlined into the compiled format versions. This means that if you
change its definition, you should explicitly call
`ibuffer-recompile-formats'.
(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil t)
(function-put 'define-ibuffer-column 'lisp-indent-function 'defun)
(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-sorter "ibuf-macs" "\
Define a method of sorting named NAME.
DOCUMENTATION is the documentation of the function, which will be called
@ -15900,9 +15928,7 @@ For sorting, the forms in BODY will be evaluated with `a' bound to one
buffer object, and `b' bound to another. BODY should return a non-nil
value if and only if `a' is \"less than\" `b'.
(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil t)
(function-put 'define-ibuffer-sorter 'lisp-indent-function 1)
(function-put 'define-ibuffer-sorter 'doc-string-elt 2)
(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-op "ibuf-macs" "\
Generate a function which operates on a buffer.
OP becomes the name of the function; if it doesn't begin with
@ -15941,9 +15967,7 @@ BODY define the operation; they are forms to evaluate per each
marked buffer. BODY is evaluated with `buf' bound to the
buffer object.
(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil t)
(function-put 'define-ibuffer-op 'lisp-indent-function 2)
(function-put 'define-ibuffer-op 'doc-string-elt 3)
(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-filter "ibuf-macs" "\
Define a filter named NAME.
DOCUMENTATION is the documentation of the function.
@ -15958,9 +15982,7 @@ not a particular buffer should be displayed or not. The forms in BODY
will be evaluated with BUF bound to the buffer object, and QUALIFIER
bound to the current value of the filter.
(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil t)
(function-put 'define-ibuffer-filter 'lisp-indent-function 2)
(function-put 'define-ibuffer-filter 'doc-string-elt 2)
(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil 'macro)
(register-definition-prefixes "ibuf-macs" '("ibuffer-"))
@ -18726,6 +18748,7 @@ This scans for ;;;###autoload forms and related things.
The first element on the command line should be the (main)
loaddefs.el output file, and the rest are the directories to
use.")
(load "theme-loaddefs.el" t)
(register-definition-prefixes "loaddefs-gen" '("autoload-" "generated-autoload-" "loaddefs-generate--" "no-update-autoloads"))
@ -25598,8 +25621,6 @@ evaluate `rectangle-mark-mode'.
The mode's hook is called both when the mode is enabled and when
it is disabled.
\\{rectangle-mark-mode-map}
(fn &optional ARG)" t)
(register-definition-prefixes "rect" '("apply-on-rectangle" "clear-rectangle-line" "delete-" "extract-rectangle-" "killed-rectangle" "ope" "rectangle-" "spaces-string" "string-rectangle-"))

View file

@ -501,7 +501,10 @@ lost after dumping")))
bin-dest-dir)
;; Relative filename from the built uninstalled binary.
(file-relative-name file invocation-directory)))))
comp-loaded-comp-units-h))))
comp-loaded-comp-units-h)))
;; Set up the mechanism to allow inhibiting native-comp via
;; file-local variables.
(defvar comp--no-native-compile (make-hash-table :test #'equal)))
(when (hash-table-p purify-flag)
(let ((strings 0)

View file

@ -527,12 +527,12 @@
`(menu-item "Paste" yank
:enable (funcall
',(lambda ()
(and (or
(and (not buffer-read-only)
(or
(gui-backend-selection-exists-p 'CLIPBOARD)
(if (featurep 'ns) ; like paste-from-menu
(cdr yank-menu)
kill-ring))
(not buffer-read-only))))
kill-ring)))))
:help "Paste (yank) text most recently cut/copied"
:keys ,(lambda ()
(if cua-mode

View file

@ -1173,7 +1173,10 @@ allows editing it."
(defun dictionary-lookup-definition ()
"Unconditionally lookup the word at point."
(interactive)
(dictionary-new-search (cons (current-word) dictionary-default-dictionary)))
(let ((word (current-word)))
(unless word
(error "No word at point"))
(dictionary-new-search (cons word dictionary-default-dictionary))))
(defun dictionary-previous ()
"Go to the previous location in the current buffer."

View file

@ -125,6 +125,8 @@ been set up by `rfn-eshadow-setup-minibuffer'."
;; eshell.el keeps the path in `eshell-path-env'. We must change it
;; when `default-directory' points to another host.
;; This is fixed in Eshell with Emacs 29.1.
(defun tramp-eshell-directory-change ()
"Set `eshell-path-env' to $PATH of the host related to `default-directory'."
;; Remove last element of `(exec-path)', which is `exec-directory'.
@ -136,16 +138,17 @@ been set up by `rfn-eshadow-setup-minibuffer'."
(getenv "PATH"))))
(with-eval-after-load 'esh-util
(add-hook 'eshell-mode-hook
#'tramp-eshell-directory-change)
(add-hook 'eshell-directory-change-hook
#'tramp-eshell-directory-change)
(add-hook 'tramp-integration-unload-hook
(lambda ()
(remove-hook 'eshell-mode-hook
#'tramp-eshell-directory-change)
(remove-hook 'eshell-directory-change-hook
#'tramp-eshell-directory-change))))
(unless (boundp 'eshell-path-env-list)
(add-hook 'eshell-mode-hook
#'tramp-eshell-directory-change)
(add-hook 'eshell-directory-change-hook
#'tramp-eshell-directory-change)
(add-hook 'tramp-integration-unload-hook
(lambda ()
(remove-hook 'eshell-mode-hook
#'tramp-eshell-directory-change)
(remove-hook 'eshell-directory-change-hook
#'tramp-eshell-directory-change)))))
;;; Integration of recentf.el:

View file

@ -789,8 +789,8 @@ use strict;
use warnings;
use POSIX qw(getgroups);
my ($user, $passwd, $uid, $gid) = getpwuid $< ;
my $group = getgrgid $gid ;
my ( $uid, $user ) = ( $>, scalar getpwuid $> );
my ( $gid, $group ) = ( $), scalar getgrgid $) );
my @groups = map { $_ . \"(\" . getgrgid ($_) . \")\" } getgroups ();
printf \"uid=%%d(%%s) gid=%%d(%%s) groups=%%s\\n\",
@ -2827,11 +2827,14 @@ the result will be a local, non-Tramp, file name."
;; Handle empty NAME.
(when (zerop (length name)) (setq name "."))
;; On MS Windows, some special file names are not returned properly
;; by `file-name-absolute-p'.
(if (and (eq system-type 'windows-nt)
(string-match-p
(tramp-compat-rx bol (| (: alpha ":") (: (literal null-device) eol)))
name))
;; by `file-name-absolute-p'. If `tramp-syntax' is `simplified',
;; there could be the falso positive "/:".
(if (or (and (eq system-type 'windows-nt)
(string-match-p
(tramp-compat-rx bol (| (: alpha ":") (: (literal null-device) eol)))
name))
(and (not (tramp-tramp-file-p name))
(not (tramp-tramp-file-p dir))))
(tramp-run-real-handler #'expand-file-name (list name dir))
;; Unless NAME is absolute, concat DIR and NAME.
(unless (file-name-absolute-p name)

View file

@ -369,33 +369,36 @@ the result will be a local, non-Tramp, file name."
;; Unless NAME is absolute, concat DIR and NAME.
(unless (file-name-absolute-p name)
(setq name (tramp-compat-file-name-concat dir name)))
(with-parsed-tramp-file-name name nil
;; Tilde expansion if necessary. We cannot accept "~/", because
;; under sudo "~/" is expanded to the local user home directory
;; but to the root home directory.
(when (zerop (length localname))
(setq localname "~"))
(unless (file-name-absolute-p localname)
(setq localname (format "~%s/%s" user localname)))
(when (string-match
(tramp-compat-rx bos "~" (group (* (not "/"))) (group (* nonl)) eos)
localname)
(let ((uname (match-string 1 localname))
(fname (match-string 2 localname))
hname)
(when (zerop (length uname))
(setq uname user))
(when (setq hname (tramp-get-home-directory v uname))
(setq localname (concat hname fname)))))
;; Do not keep "/..".
(when (string-match-p (rx bos "/" (** 1 2 ".") eos) localname)
(setq localname "/"))
;; Do normal `expand-file-name' (this does "~user/", "/./" and "/../").
(tramp-make-tramp-file-name
v (if (string-prefix-p "~" localname)
localname
(tramp-run-real-handler
#'expand-file-name (list localname))))))
;; If NAME is not a Tramp file, run the real handler.
(if (not (tramp-tramp-file-p name))
(tramp-run-real-handler #'expand-file-name (list name))
(with-parsed-tramp-file-name name nil
;; Tilde expansion if necessary. We cannot accept "~/", because
;; under sudo "~/" is expanded to the local user home directory
;; but to the root home directory.
(when (zerop (length localname))
(setq localname "~"))
(unless (file-name-absolute-p localname)
(setq localname (format "~%s/%s" user localname)))
(when (string-match
(tramp-compat-rx bos "~" (group (* (not "/"))) (group (* nonl)) eos)
localname)
(let ((uname (match-string 1 localname))
(fname (match-string 2 localname))
hname)
(when (zerop (length uname))
(setq uname user))
(when (setq hname (tramp-get-home-directory v uname))
(setq localname (concat hname fname)))))
;; Do not keep "/..".
(when (string-match-p (rx bos "/" (** 1 2 ".") eos) localname)
(setq localname "/"))
;; Do normal `expand-file-name' (this does "~user/", "/./" and "/../").
(tramp-make-tramp-file-name
v (if (string-prefix-p "~" localname)
localname
(tramp-run-real-handler
#'expand-file-name (list localname)))))))
(defun tramp-sudoedit-remote-acl-p (vec)
"Check, whether ACL is enabled on the remote host."

View file

@ -1526,7 +1526,8 @@ same connection. Make a copy in order to avoid side effects."
;; Comparison of file names is performed by `tramp-equal-remote'.
(defun tramp-file-name-equal-p (vec1 vec2)
"Check, whether VEC1 and VEC2 denote the same `tramp-file-name'."
"Check, whether VEC1 and VEC2 denote the same `tramp-file-name'.
LOCALNAME and HOP do not count."
(and (tramp-file-name-p vec1) (tramp-file-name-p vec2)
(equal (tramp-file-name-unify vec1)
(tramp-file-name-unify vec2))))

View file

@ -295,6 +295,9 @@ buffers (yet) -- that will be amended in a future version."
(defvar-local outline--use-buttons nil
"Non-nil when buffer displays clickable buttons on the headings.")
(defvar-local outline-minor-mode-insert-buttons nil
"Non-nil when it's allowed to modify buffer to insert buttons.")
(defvar-local outline--use-rtl nil
"Non-nil when direction of clickable buttons is right-to-left.")
@ -339,17 +342,26 @@ Note that this feature is meant to be used in editing buffers."
:version "29.1")
(define-icon outline-open-in-margins outline-open
'((image "outline-open.svg" "outline-open.pbm" :height 10))
'((image "outline-open.svg" "outline-open.pbm" :height 10)
(emoji "🔽")
(symbol "")
(text "v"))
"Icon used for buttons for opened sections in margins."
:version "29.1")
(define-icon outline-close-in-margins outline-close
'((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation -90))
'((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation -90)
(emoji "▶️")
(symbol "")
(text ">"))
"Icon used for buttons for closed sections in margins."
:version "29.1")
(define-icon outline-close-rtl-in-margins outline-close-rtl
'((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation 90))
'((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation 90)
(emoji "◀️")
(symbol "")
(text "<"))
"Right-to-left icon used for closed sections in margins."
:version "29.1")
@ -513,7 +525,8 @@ See the command `outline-mode' for more information on this mode."
(setq-local left-margin-width (1+ left-margin-width)))
(setq-local fringes-outside-margins t)
;; Force display of margins
(set-window-buffer nil (window-buffer)))
(when (eq (current-buffer) (window-buffer))
(set-window-buffer nil (window-buffer))))
(when (or outline--use-buttons outline--use-margins)
(add-hook 'after-change-functions
#'outline--fix-buttons-after-change nil t))
@ -551,7 +564,8 @@ See the command `outline-mode' for more information on this mode."
(setq-local left-margin-width (1- left-margin-width)))
(setq-local fringes-outside-margins nil)
;; Force removal of margins
(set-window-buffer nil (window-buffer)))))
(when (eq (current-buffer) (window-buffer))
(set-window-buffer nil (window-buffer))))))
(defvar-local outline-heading-alist ()
"Alist associating a heading for every possible level.
@ -1657,18 +1671,24 @@ With a prefix argument, show headings up to that LEVEL."
(if outline--use-rtl
'outline-close-rtl
'outline-close)
'outline-open)))
(inhibit-read-only t))
'outline-open))))
;; In editing buffers we use overlays only, but in other buffers
;; we use a mix of text properties, text and overlays to make
;; movement commands work more logically.
(when (derived-mode-p 'special-mode)
(put-text-property (point) (1+ (point)) 'face (plist-get icon 'face)))
(if-let ((image (plist-get icon 'image)))
(overlay-put o 'display image)
(overlay-put o 'display (concat (plist-get icon 'string)
(string (char-after (point)))))
(overlay-put o 'face (plist-get icon 'face))))
(if outline-minor-mode-insert-buttons
(let ((inhibit-read-only t))
(put-text-property (point) (1+ (point)) 'face (plist-get icon 'face))
(if-let ((image (plist-get icon 'image)))
(overlay-put o 'display image)
(overlay-put o 'display (concat (plist-get icon 'string)
(string (char-after (point)))))
(overlay-put o 'face (plist-get icon 'face))))
(overlay-put
o 'before-string
(propertize " "
'display
(or (plist-get icon 'image)
(plist-get icon 'string))))))
o))
(defun outline--make-margin-overlay (type)
@ -1699,7 +1719,7 @@ With a prefix argument, show headings up to that LEVEL."
(beginning-of-line)
(if use-margins
(outline--make-margin-overlay 'open)
(when (derived-mode-p 'special-mode)
(when outline-minor-mode-insert-buttons
(let ((inhibit-read-only t))
(insert " ")
(beginning-of-line)))
@ -1716,7 +1736,7 @@ With a prefix argument, show headings up to that LEVEL."
(beginning-of-line)
(if use-margins
(outline--make-margin-overlay 'close)
(when (derived-mode-p 'special-mode)
(when outline-minor-mode-insert-buttons
(let ((inhibit-read-only t))
(insert " ")
(beginning-of-line)))

View file

@ -60,7 +60,6 @@
(cc-bytecomp-defun region-active-p) ; XEmacs
(cc-bytecomp-defvar mark-active) ; Emacs
(cc-bytecomp-defvar deactivate-mark) ; Emacs
(cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs
(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs
(cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21
(cc-bytecomp-defun string-to-syntax) ; Emacs 21

View file

@ -9055,7 +9055,8 @@ multi-line strings (but not C++, for example)."
(c-forward-<>-arglist t)
(c-forward-syntactic-ws))
(let ((start (point)) pos res name-res id-start id-end id-range)
(let ((start (point)) pos res name-res id-start id-end id-range
post-prefix-pos)
;; Skip leading type modifiers. If any are found we know it's a
;; prefix of a type.
@ -9067,6 +9068,7 @@ multi-line strings (but not C++, for example)."
(c-forward-syntactic-ws)
(or (eq res 'no-id)
(setq res 'prefix))))
(setq post-prefix-pos (point))
(cond
((looking-at c-typeof-key) ; e.g. C++'s "decltype".
@ -9099,9 +9101,12 @@ multi-line strings (but not C++, for example)."
(setq name-res (c-forward-name))
(setq res (not (null name-res)))
(when (eq name-res t)
;; In many languages the name can be used without the
;; prefix, so we add it to `c-found-types'.
(c-add-type pos (point))
;; With some keywords the name can be used without the prefix, so we
;; add the name to `c-found-types' when this is the case.
(when (save-excursion
(goto-char post-prefix-pos)
(looking-at c-self-contained-typename-key))
(c-add-type pos (point)))
(when (and c-record-type-identifiers
c-last-identifier-range)
(c-record-type-id c-last-identifier-range)))

View file

@ -2294,11 +2294,22 @@ declaration with a type as a default value. This is used only in
C++ Mode, e.g. \"<typename X = Y>\"."
t nil
c++ '("class" "typename"))
(c-lang-defconst c-template-typename-key
t (c-make-keywords-re t (c-lang-const c-template-typename-kwds)))
(c-lang-defvar c-template-typename-key (c-lang-const c-template-typename-key))
(c-lang-defconst c-self-contained-typename-kwds
"Keywords where the following name is a type name which can be
used in declarations without the keyword."
t nil
c++ '("typename"))
(c-lang-defconst c-self-contained-typename-key
;; Adorned regexp matching `c-self-contained-typename-key'.
t (c-make-keywords-re t (c-lang-const c-self-contained-typename-kwds)))
(c-lang-defvar c-self-contained-typename-key
(c-lang-const c-self-contained-typename-key))
(c-lang-defconst c-type-prefix-kwds
"Keywords where the following name - if any - is a type name, and
where the keyword together with the symbol works as a type in

View file

@ -1826,8 +1826,8 @@ or elsewhere, return a 1-line docstring."
(eq 'function (aref elisp--eldoc-last-data 2)))
(aref elisp--eldoc-last-data 1))
(t
(let* ((advertised (gethash (indirect-function sym)
advertised-signature-table t))
(let* ((advertised (get-advertised-calling-convention
(indirect-function sym)))
doc
(args
(cond

View file

@ -1,7 +1,6 @@
;;; fortran.el --- Fortran mode for GNU Emacs -*- lexical-binding: t -*-
;; Copyright (C) 1986, 1993-1995, 1997-2022 Free Software Foundation,
;; Inc.
;; Copyright (C) 1986-2022 Free Software Foundation, Inc.
;; Author: Michael D. Prange <prange@erl.mit.edu>
;; Maintainer: emacs-devel@gnu.org
@ -624,34 +623,32 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
st)
"Syntax table used to parse Fortran expressions for printing in GUD.")
(defvar fortran-mode-map
(let ((map (make-sparse-keymap)))
(define-key map ";" 'fortran-abbrev-start)
(define-key map "\C-c;" 'fortran-comment-region)
;; The default comment-dwim does at least as much as this.
;;; (define-key map "\M-;" 'fortran-indent-comment)
(define-key map "\M-\n" 'fortran-split-line)
(define-key map "\M-\C-n" 'fortran-end-of-block)
(define-key map "\M-\C-p" 'fortran-beginning-of-block)
(define-key map "\M-\C-q" 'fortran-indent-subprogram)
(define-key map "\C-c\C-w" 'fortran-window-create-momentarily)
(define-key map "\C-c\C-r" 'fortran-column-ruler)
(define-key map "\C-c\C-p" 'fortran-previous-statement)
(define-key map "\C-c\C-n" 'fortran-next-statement)
(define-key map "\C-c\C-d" 'fortran-join-line) ; like f90
(define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation
(define-key map "0" 'fortran-electric-line-number)
(define-key map "1" 'fortran-electric-line-number)
(define-key map "2" 'fortran-electric-line-number)
(define-key map "3" 'fortran-electric-line-number)
(define-key map "4" 'fortran-electric-line-number)
(define-key map "5" 'fortran-electric-line-number)
(define-key map "6" 'fortran-electric-line-number)
(define-key map "7" 'fortran-electric-line-number)
(define-key map "8" 'fortran-electric-line-number)
(define-key map "9" 'fortran-electric-line-number)
map)
"Keymap used in Fortran mode.")
(defvar-keymap fortran-mode-map
:doc "Keymap used in Fortran mode."
";" #'fortran-abbrev-start
"C-c ;" #'fortran-comment-region
;; The default comment-dwim does at least as much as this.
;; "M-;" #'fortran-indent-comment
"C-M-j" #'fortran-split-line
"C-M-n" #'fortran-end-of-block
"C-M-p" #'fortran-beginning-of-block
"C-M-q" #'fortran-indent-subprogram
"C-c C-w" #'fortran-window-create-momentarily
"C-c C-r" #'fortran-column-ruler
"C-c C-p" #'fortran-previous-statement
"C-c C-n" #'fortran-next-statement
"C-c C-d" #'fortran-join-line ; like f90
"M-^" #'fortran-join-line ; subvert delete-indentation
"0" #'fortran-electric-line-number
"1" #'fortran-electric-line-number
"2" #'fortran-electric-line-number
"3" #'fortran-electric-line-number
"4" #'fortran-electric-line-number
"5" #'fortran-electric-line-number
"6" #'fortran-electric-line-number
"7" #'fortran-electric-line-number
"8" #'fortran-electric-line-number
"9" #'fortran-electric-line-number)
(define-abbrev-table 'fortran-mode-abbrev-table

View file

@ -4080,15 +4080,18 @@ using that one instead of current buffer's process."
(buffer-substring-no-properties line-start (point)))
(buffer-substring-no-properties line-start (point))))
(start
(save-excursion
(if (not (re-search-backward
(python-rx
(or whitespace open-paren close-paren string-delimiter simple-operator))
line-start
t 1))
line-start
(forward-char (length (match-string-no-properties 0)))
(point))))
(if (< (point) line-start)
(point)
(save-excursion
(if (not (re-search-backward
(python-rx
(or whitespace open-paren close-paren
string-delimiter simple-operator))
line-start
t 1))
line-start
(forward-char (length (match-string-no-properties 0)))
(point)))))
(end (point))
(prompt-boundaries
(with-current-buffer (process-buffer process)
@ -4102,7 +4105,10 @@ using that one instead of current buffer's process."
(with-current-buffer (process-buffer process)
(cond ((or (null prompt)
(and is-shell-buffer
(< (point) (cdr prompt-boundaries))))
(< (point) (cdr prompt-boundaries)))
(and (not is-shell-buffer)
(string-match-p
python-shell-prompt-pdb-regexp prompt)))
#'ignore)
((or (not python-shell-completion-native-enable)
;; Even if native completion is enabled, for

View file

@ -344,7 +344,7 @@ in compilation warnings about unused variables.
;; FIXME: This let often leads to "unused var" warnings.
`((let ((,var ,counter)) ,@(cddr spec)))))))
(defmacro declare (&rest _specs)
(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
@ -355,8 +355,16 @@ The possible values of SPECS are specified by
`defun-declarations-alist' and `macro-declarations-alist'.
For more information, see info node `(elisp)Declare Form'."
;; FIXME: edebug spec should pay attention to defun-declarations-alist.
nil)
;; `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.

View file

@ -73,12 +73,9 @@
(defun emacs-news--mode-common ()
(setq-local font-lock-defaults '(emacs-news-mode-font-lock-keywords t))
;; This `outline-regexp' matches leading spaces inserted
;; by the current implementation of `outline-minor-mode-use-buttons'.
(setq-local outline-regexp "\\(?: +\\)?\\(\\*+\\) "
outline-level (lambda () (length (match-string 1)))
outline-minor-mode-cycle t
outline-minor-mode-highlight 'append)
(setq-local outline-minor-mode-cycle t
outline-minor-mode-highlight 'append
outline-minor-mode-use-margins t)
(outline-minor-mode)
(setq-local imenu-generic-expression outline-imenu-generic-expression)
(emacs-etc--hide-local-variables))

View file

@ -1689,6 +1689,50 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
backend
patch-string))
(defun vc-default-checkin-patch (_backend patch-string comment)
(pcase-let* ((`(,backend ,files) (with-temp-buffer
(insert patch-string)
(diff-vc-deduce-fileset)))
(tmpdir (make-temp-file "vc-checkin-patch" t)))
(dolist (f files)
(make-directory (file-name-directory (expand-file-name f tmpdir)) t)
(copy-file (expand-file-name f)
(expand-file-name f tmpdir)))
(unwind-protect
(progn
(dolist (f files)
(with-current-buffer (find-file-noselect f)
(vc-revert-file buffer-file-name)))
(with-temp-buffer
;; Trying to support CVS too. Assuming that vc-diff
;; there will usually have diff root in default-directory.
(when (vc-find-backend-function backend 'root)
(setq-local default-directory
(vc-call-backend backend 'root (car files))))
(unless (eq 0
(call-process-region patch-string
nil
"patch"
nil
t
nil
"-p1"
"-r" null-device
"--no-backup-if-mismatch"
"-i" "-"))
(user-error "Patch failed: %s" (buffer-string))))
(dolist (f files)
(with-current-buffer (get-file-buffer f)
(revert-buffer t t t)))
(vc-call-backend backend 'checkin files comment))
(dolist (f files)
(copy-file (expand-file-name f tmpdir)
(expand-file-name f)
t)
(with-current-buffer (get-file-buffer f)
(revert-buffer t t t)))
(delete-directory tmpdir t))))
;;; Additional entry points for examining version histories
;; (defun vc-default-diff-tree (backend dir rev1 rev2)
@ -3377,12 +3421,12 @@ revisions, those revisions will be used."
revisions)))
(if vc-prepare-patches-separately
(dolist (patch (reverse patches)
(message "Prepared %d patches..." (length patches)))
(message "Prepared %d patch%s..." (length patches)
(if (length> patches 1) "es" "")))
(compose-mail addressee
(plist-get patch :subject)
nil nil nil nil
`((kill-buffer ,(plist-get patch :buffer))
(exit-recursive-edit)))
`((kill-buffer ,(plist-get patch :buffer))))
(rfc822-goto-eoh) (forward-line)
(save-excursion ;don't jump to the end
(insert-buffer-substring

View file

@ -5868,8 +5868,21 @@ The last directory of this list is assumed to be the system one. */);
Vnative_comp_eln_load_path = Fcons (build_string ("../native-lisp/"), Qnil);
DEFVAR_BOOL ("comp-enable-subr-trampolines", comp_enable_subr_trampolines,
doc: /* If non-nil enable primitive trampoline synthesis.
This makes primitive functions redefinable or advisable effectively. */);
doc: /* If non-nil, enable primitive trampoline synthesis.
This makes Emacs respect redefinition or advises of primitive functions
when they are called from Lisp code natively-compiled at `native-comp-speed'
of 2.
By default, this is enabled, and when Emacs sees a redefined or advised
primitive called from natively-compiled Lisp, it generates a trampoline
for it on-the-fly.
Disabling this, when a trampoline for a redefined or advised primitive is
not available from previous compilations, means that such redefinition
or advise will not have effect on calls from natively-compiled Lisp code.
That is, calls to primitives without existing trampolines from
natively-compiled Lisp will behave as if the primitive was called
directly from C. */);
DEFVAR_LISP ("comp-installed-trampolines-h", Vcomp_installed_trampolines_h,
doc: /* Hash table subr-name -> installed trampoline.

View file

@ -3152,10 +3152,19 @@ redraw_frame (struct frame *f)
update_begin (f);
if (FRAME_MSDOS_P (f))
FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
if (FRAME_WINDOW_P (f))
/* Garbage the frame now. Otherwise, platforms that support
double buffering will display the blank contents of the frame
even though the frame should be redrawn at some point in the
future. */
SET_FRAME_GARBAGED (f);
clear_frame (f);
clear_current_matrices (f);
update_end (f);
fset_redisplay (f);
/* Mark all windows as inaccurate, so that every window will have
its redisplay done. */
mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);

View file

@ -232,6 +232,9 @@ haiku_frame_up_to_date (struct frame *f)
be_evict_font_cache ();
up_to_date_count = 0;
}
/* Mark the frame as complete. */
FRAME_COMPLETE_P (f) = true;
unblock_input ();
}
@ -265,6 +268,8 @@ haiku_clear_frame (struct frame *f)
mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
FRAME_COMPLETE_P (f) = false;
block_input ();
BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
FRAME_PIXEL_HEIGHT (f));
@ -1436,6 +1441,9 @@ haiku_clip_to_row (struct window *w, struct glyph_row *row,
static void
haiku_update_begin (struct frame *f)
{
/* Mark the frame as incomplete so it is not flushed upon handling
input. */
FRAME_COMPLETE_P (f) = false;
}
static void
@ -2959,6 +2967,10 @@ haiku_flush (struct frame *f)
if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
haiku_flip_buffers (f);
/* The frame is complete again as its contents were just
flushed. */
FRAME_COMPLETE_P (f) = true;
if (FRAME_VISIBLE_P (f) && !FRAME_TOOLTIP_P (f))
BWindow_Flush (FRAME_HAIKU_WINDOW (f));
}
@ -3086,10 +3098,15 @@ haiku_make_fullscreen_consistent (struct frame *f)
static void
haiku_flush_dirty_back_buffer_on (struct frame *f)
{
if (!FRAME_GARBAGED_P (f)
&& !buffer_flipping_blocked_p ()
&& FRAME_DIRTY_P (f))
haiku_flip_buffers (f);
if (FRAME_GARBAGED_P (f)
|| buffer_flipping_blocked_p ()
/* If the frame is not already up to date, do not flush buffers
on input, as that will result in flicker. */
|| !FRAME_COMPLETE_P (f)
|| !FRAME_DIRTY_P (f))
return;
haiku_flip_buffers (f);
}
/* N.B. that support for TYPE must be explicitly added to
@ -3135,6 +3152,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
int button_or_motion_p, do_help;
enum haiku_event_type type;
struct input_event inev, inev2;
struct frame *mouse_frame;
message_count = 0;
button_or_motion_p = 0;
@ -3252,9 +3270,13 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
|| !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
|| !EQ (f->tab_bar_window, hlinfo->mouse_face_window)))
{
mouse_frame = hlinfo->mouse_face_mouse_frame;
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
haiku_flush_dirty_back_buffer_on (f);
if (mouse_frame)
haiku_flush_dirty_back_buffer_on (mouse_frame);
}
inev.code = b->keysym ? b->keysym : b->multibyte_char;

View file

@ -174,6 +174,10 @@ struct haiku_output
displayed yet. */
bool_bf dirty_p : 1;
/* Whether or not the frame is complete, i.e. safe to flush on
input. */
bool_bf complete_p : 1;
struct font *font;
/* The pending position we're waiting for. */
@ -275,6 +279,7 @@ struct scroll_bar
#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
#define FRAME_DIRTY_P(f) (FRAME_OUTPUT_DATA (f)->dirty_p)
#define FRAME_COMPLETE_P(f) (FRAME_OUTPUT_DATA (f)->complete_p)
#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1)
#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku)
#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)

View file

@ -8443,7 +8443,17 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
unblock_input ();
XSETFRAME (frame, f);
attributes = Fx_display_monitor_attributes_list (frame);
#if defined HAVE_XRANDR || defined USE_GTK
if (!NILP (FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list))
/* Use cached values if available to avoid fetching the
monitor list from the X server. If XRandR is not
available, then fetching the attributes will probably not
sync anyway, and will thus be relatively harmless. */
attributes = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list;
else
#endif
attributes = Fx_display_monitor_attributes_list (frame);
/* Try to determine the monitor where the mouse pointer is and
its geometry. See bug#22549. */
@ -8693,9 +8703,6 @@ Text larger than the specified size is clipped. */)
int old_windows_or_buffers_changed = windows_or_buffers_changed;
specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object window, size, tip_buf;
Window child;
XWindowAttributes child_attrs;
int dest_x_return, dest_y_return;
bool displayed;
#ifdef ENABLE_CHECKING
struct glyph_row *row, *end;
@ -8946,41 +8953,6 @@ Text larger than the specified size is clipped. */)
/* Show tooltip frame. */
block_input ();
/* If the display is composited, then WM_TRANSIENT_FOR must be set
as well, or else the compositing manager won't display
decorations correctly, even though the tooltip window is override
redirect. See
https://specifications.freedesktop.org/wm-spec/1.4/ar01s08.html
Perhaps WM_TRANSIENT_FOR should be used in place of
override-redirect anyway. The ICCCM only recommends
override-redirect if the pointer will be grabbed. */
if (XTranslateCoordinates (FRAME_X_DISPLAY (f),
FRAME_DISPLAY_INFO (f)->root_window,
FRAME_DISPLAY_INFO (f)->root_window,
root_x, root_y, &dest_x_return,
&dest_y_return, &child)
&& child != None)
{
/* But only if the child is not override-redirect, which can
happen if the pointer is above a menu. */
if (XGetWindowAttributes (FRAME_X_DISPLAY (f),
child, &child_attrs)
|| child_attrs.override_redirect)
XDeleteProperty (FRAME_X_DISPLAY (tip_f),
FRAME_X_WINDOW (tip_f),
FRAME_DISPLAY_INFO (tip_f)->Xatom_wm_transient_for);
else
XSetTransientForHint (FRAME_X_DISPLAY (tip_f),
FRAME_X_WINDOW (tip_f), child);
}
else
XDeleteProperty (FRAME_X_DISPLAY (tip_f),
FRAME_X_WINDOW (tip_f),
FRAME_DISPLAY_INFO (tip_f)->Xatom_wm_transient_for);
#ifndef USE_XCB
XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
root_x, root_y, width, height);
@ -9452,13 +9424,21 @@ usual X keysyms. Value is `lambda' if we cannot determine if both keys are
present and mapped to the usual X keysyms. */)
(Lisp_Object frame)
{
#ifdef HAVE_XKB
XkbDescPtr kb;
struct frame *f;
Display *dpy;
Lisp_Object have_keys;
int delete_keycode, backspace_keycode, i;
#endif
#ifndef HAVE_XKB
return Qlambda;
#else
XkbDescPtr kb;
struct frame *f = decode_window_system_frame (frame);
Display *dpy = FRAME_X_DISPLAY (f);
Lisp_Object have_keys;
delete_keycode = 0;
backspace_keycode = 0;
f = decode_window_system_frame (frame);
dpy = FRAME_X_DISPLAY (f);
if (!FRAME_DISPLAY_INFO (f)->supports_xkb)
return Qlambda;
@ -9474,50 +9454,39 @@ present and mapped to the usual X keysyms. */)
XK_Delete are mapped to any key. But if any of those are mapped to
some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
user doesn't know about it, it is better to return false here.
It is more obvious to the user what to do if she/he has two keys
It is more obvious to the user what to do if there are two keys
clearly marked with names/symbols and one key does something not
expected (i.e. she/he then tries the other).
expected (and the user then tries the other).
The cases where Backspace/Delete is mapped to some other key combination
are rare, and in those cases, normal-erase-is-backspace can be turned on
manually. */
have_keys = Qnil;
kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
if (kb)
kb = FRAME_DISPLAY_INFO (f)->xkb_desc;
if (kb && kb->names)
{
int delete_keycode = 0, backspace_keycode = 0, i;
if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
for (i = kb->min_key_code; (i < kb->max_key_code
&& (delete_keycode == 0
|| backspace_keycode == 0));
++i)
{
for (i = kb->min_key_code;
(i < kb->max_key_code
&& (delete_keycode == 0 || backspace_keycode == 0));
++i)
{
/* The XKB symbolic key names can be seen most easily in
the PS file generated by `xkbprint -label name
$DISPLAY'. */
if (memcmp ("DELE", kb->names->keys[i].name, 4) == 0)
delete_keycode = i;
else if (memcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
backspace_keycode = i;
}
XkbFreeNames (kb, 0, True);
/* The XKB symbolic key names can be seen most easily in
the PS file generated by `xkbprint -label name
$DISPLAY'. */
if (!memcmp ("DELE", kb->names->keys[i].name, 4))
delete_keycode = i;
else if (!memcmp ("BKSP", kb->names->keys[i].name, 4))
backspace_keycode = i;
}
/* As of libX11-1.6.2, XkbGetMap manual says that you should use
XkbFreeClientMap to free the data returned by XkbGetMap. But
this function just frees the data referenced from KB and not
KB itself. To free KB as well, call XkbFreeKeyboard. */
XkbFreeKeyboard (kb, XkbAllMapComponentsMask, True);
if (delete_keycode
&& backspace_keycode
if (delete_keycode && backspace_keycode
&& XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
&& XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
have_keys = Qt;
}
else
/* The keyboard names couldn't be obtained for some reason. */
have_keys = Qlambda;
unblock_input ();
return have_keys;
#endif

View file

@ -1521,26 +1521,15 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
if (use_pos_func)
{
Window dummy_window;
/* Not invoked by a click. pop up at x/y. */
pos_func = menu_position_func;
/* Adjust coordinates to be root-window-relative. */
block_input ();
XTranslateCoordinates (FRAME_X_DISPLAY (f),
/* From-window, to-window. */
FRAME_X_WINDOW (f),
FRAME_DISPLAY_INFO (f)->root_window,
/* From-position, to-position. */
x, y, &x, &y,
/* Child of win. */
&dummy_window);
x_translate_coordinates_to_root (f, x, y, &x, &y);
#ifdef HAVE_GTK3
/* Use window scaling factor to adjust position for hidpi screens. */
/* Use window scaling factor to adjust position for scaled
outputs. */
x /= xg_get_scale (f);
y /= xg_get_scale (f);
#endif
@ -1743,7 +1732,6 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
XButtonPressedEvent *event = &(dummy.xbutton);
LWLIB_ID menu_id;
Widget menu;
Window dummy_window;
#if defined HAVE_XINPUT2 && defined USE_MOTIF
XEvent property_dummy;
Atom property_atom;
@ -1775,17 +1763,7 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
/* Adjust coordinates to be root-window-relative. */
block_input ();
x += FRAME_LEFT_SCROLL_BAR_AREA_WIDTH (f);
XTranslateCoordinates (FRAME_X_DISPLAY (f),
/* From-window, to-window. */
FRAME_X_WINDOW (f),
FRAME_DISPLAY_INFO (f)->root_window,
/* From-position, to-position. */
x, y, &x, &y,
/* Child of win. */
&dummy_window);
x_translate_coordinates_to_root (f, x, y, &x, &y);
unblock_input ();
event->x_root = x;
@ -2569,9 +2547,6 @@ Lisp_Object
x_menu_show (struct frame *f, int x, int y, int menuflags,
Lisp_Object title, const char **error_name)
{
#ifdef HAVE_X_WINDOWS
Window dummy_window;
#endif
Window root;
XMenu *menu;
int pane, selidx, lpane, status;
@ -2620,17 +2595,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
inhibit_garbage_collection ();
#ifdef HAVE_X_WINDOWS
XTranslateCoordinates (FRAME_X_DISPLAY (f),
/* From-window, to-window. */
FRAME_X_WINDOW (f),
FRAME_DISPLAY_INFO (f)->root_window,
/* From-position, to-position. */
x, y, &x, &y,
/* Child of win. */
&dummy_window);
x_translate_coordinates_to_root (f, x, y, &x, &y);
#else
/* MSDOS without X support. */
x += f->left_pos;

View file

@ -2376,12 +2376,19 @@ On Nextstep, TERMINAL is unused. */)
{
Window owner;
Atom atom;
#ifdef HAVE_XFIXES
Window temp_owner;
#endif
struct frame *f = frame_for_x_selection (terminal);
struct x_display_info *dpyinfo;
CHECK_SYMBOL (selection);
if (NILP (selection)) selection = QPRIMARY;
if (EQ (selection, Qt)) selection = QSECONDARY;
if (NILP (selection))
selection = QPRIMARY;
if (EQ (selection, Qt))
selection = QSECONDARY;
if (!f)
return Qnil;
@ -2392,10 +2399,22 @@ On Nextstep, TERMINAL is unused. */)
return Qt;
atom = symbol_to_x_atom (dpyinfo, selection);
if (atom == 0) return Qnil;
if (!atom)
return Qnil;
#ifdef HAVE_XFIXES
/* See if this information can be obtained without a roundtrip. */
temp_owner = x_find_selection_owner (dpyinfo, atom);
if (temp_owner != X_INVALID_WINDOW)
return (temp_owner != None ? Qt : Qnil);
#endif
block_input ();
owner = XGetSelectionOwner (dpyinfo->display, atom);
unblock_input ();
return (owner ? Qt : Qnil);
}

View file

@ -7044,6 +7044,13 @@ x_update_begin (struct frame *f)
#else
/* Nothing to do. */
#endif
#ifdef HAVE_XDBE
if (FRAME_X_DOUBLE_BUFFERED_P (f))
/* The frame is no longer complete, as it is in the midst of an
update. */
FRAME_X_COMPLETE_P (f) = false;
#endif
}
/* Draw a vertical window border from (x,y0) to (x,y1) */
@ -7190,6 +7197,10 @@ x_flip_and_flush (struct frame *f)
#ifdef HAVE_XDBE
if (FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
/* The frame is complete again as its contents were just
flushed. */
FRAME_X_COMPLETE_P (f) = true;
#endif
x_flush (f);
unblock_input ();
@ -7240,6 +7251,9 @@ XTframe_up_to_date (struct frame *f)
if (!buffer_flipping_blocked_p ()
&& FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
/* The frame is now complete, as its contents have been drawn. */
FRAME_X_COMPLETE_P (f) = true;
#endif
#ifdef HAVE_XSYNC
@ -10806,6 +10820,7 @@ x_clear_frame (struct frame *f)
/* We have to clear the scroll bars. If we have changed colors or
something like that, then they should be notified. */
x_scroll_bar_clear (f);
unblock_input ();
}
@ -10857,7 +10872,7 @@ x_show_hourglass (struct frame *f)
(xcb_window_t) x->hourglass_window,
parent, 0, 0, FRAME_PIXEL_WIDTH (f),
FRAME_PIXEL_HEIGHT (f), 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
XCB_WINDOW_CLASS_INPUT_ONLY,
XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
&cursor);
#endif
@ -13644,6 +13659,43 @@ x_translate_coordinates (struct frame *f, int root_x, int root_y,
}
}
/* Translate the given coordinates from the edit window of FRAME,
taking into account any cached root window offsets. This is mainly
used from the popup menu code. */
void
x_translate_coordinates_to_root (struct frame *f, int x, int y,
int *x_out, int *y_out)
{
struct x_output *output;
Window dummy;
output = FRAME_X_OUTPUT (f);
if (output->window_offset_certain_p)
{
/* Use the cached root window offset. */
*x_out = x + output->root_x;
*y_out = y + output->root_y;
return;
}
/* Otherwise, do the transform manually and compute and cache the
root window position. */
if (!XTranslateCoordinates (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_DISPLAY_INFO (f)->root_window,
x, y, x_out, y_out, &dummy))
*x_out = 0, *y_out = 0;
else
{
/* Cache the root window offset of the edit window. */
output->window_offset_certain_p = true;
output->root_x = *x_out - x;
output->root_y = *y_out - y;
}
}
/* The same, but for an XIDeviceEvent. */
#ifdef HAVE_XINPUT2
@ -17033,18 +17085,21 @@ x_net_wm_state (struct frame *f, Window window)
/* Flip back buffers on F if it has undrawn content. */
#ifdef HAVE_XDBE
static void
flush_dirty_back_buffer_on (struct frame *f)
x_flush_dirty_back_buffer_on (struct frame *f)
{
block_input ();
if (!FRAME_GARBAGED_P (f)
&& !buffer_flipping_blocked_p ()
&& FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
unblock_input ();
}
#ifdef HAVE_XDBE
if (FRAME_GARBAGED_P (f)
|| buffer_flipping_blocked_p ()
/* If the frame is not already up to date, do not flush buffers
on input, as that will result in flicker. */
|| !FRAME_X_COMPLETE_P (f)
|| !FRAME_X_NEED_BUFFER_FLIP (f))
return;
show_back_buffer (f);
#endif
}
#ifdef HAVE_GTK3
void
@ -17798,6 +17853,46 @@ x_handle_wm_state (struct frame *f, struct input_event *ie)
XFree (data);
}
#ifdef HAVE_XFIXES
static bool
x_handle_selection_monitor_event (struct x_display_info *dpyinfo,
XEvent *event)
{
XFixesSelectionNotifyEvent *notify;
int i;
notify = (XFixesSelectionNotifyEvent *) event;
if (notify->window != dpyinfo->selection_tracking_window)
return false;
for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
{
/* We don't have to keep track of timestamps here. */
if (notify->selection == dpyinfo->monitored_selections[i].name)
dpyinfo->monitored_selections[i].owner = notify->owner;
}
return true;
}
Window
x_find_selection_owner (struct x_display_info *dpyinfo, Atom selection)
{
int i;
for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
{
if (selection == dpyinfo->monitored_selections[i].name)
return dpyinfo->monitored_selections[i].owner;
}
return X_INVALID_WINDOW;
}
#endif
/* Handles the XEvent EVENT on display DPYINFO.
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
@ -17824,7 +17919,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Time gen_help_time UNINIT;
#endif
ptrdiff_t nbytes = 0;
struct frame *any, *f = NULL;
struct frame *any, *f = NULL, *mouse_frame;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
/* This holds the state XLookupString needs to implement dead keys
and other tricks known as "compose processing". _X Window System_
@ -19148,9 +19243,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
)
{
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
}
mouse_frame = hlinfo->mouse_face_mouse_frame;
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
if (mouse_frame)
x_flush_dirty_back_buffer_on (mouse_frame);
}
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
if (f == 0)
@ -19630,6 +19730,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
x_flush_dirty_back_buffer_on (xvw->frame);
}
if (any_help_event_p)
@ -19783,6 +19884,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
certainly no longer on any text in the frame. */
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
x_flush_dirty_back_buffer_on (f);
}
/* Generate a nil HELP_EVENT to cancel a help-echo.
@ -19840,7 +19942,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
help_echo_string = Qnil;
if (hlinfo->mouse_face_hidden)
{
{
hlinfo->mouse_face_hidden = false;
clear_mouse_face (hlinfo);
}
@ -20171,6 +20273,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
do_help = 1;
if (f)
x_flush_dirty_back_buffer_on (f);
goto OTHER;
}
@ -20467,7 +20572,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
int old_left = f->left_pos;
int old_top = f->top_pos;
Lisp_Object frame = Qnil;
Lisp_Object frame;
XSETFRAME (frame, f);
@ -20837,9 +20942,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
tab_bar_arg = handle_tab_bar_click
(f, x, y, event->xbutton.type == ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
{
tab_bar_arg = handle_tab_bar_click
(f, x, y, event->xbutton.type == ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
x_flush_dirty_back_buffer_on (f);
}
}
#if ! defined (USE_GTK)
@ -20857,9 +20965,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| f->last_tool_bar_item != -1));
if (tool_bar_p && event->xbutton.button < 4)
handle_tool_bar_click
(f, x, y, event->xbutton.type == ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
{
handle_tool_bar_click
(f, x, y, event->xbutton.type == ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
x_flush_dirty_back_buffer_on (f);
}
}
#endif /* !USE_GTK */
@ -21398,6 +21509,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
certainly no longer on any text in the frame. */
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
x_flush_dirty_back_buffer_on (f);
}
/* Generate a nil HELP_EVENT to cancel a help-echo.
@ -22073,6 +22185,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
do_help = 1;
}
if (f)
x_flush_dirty_back_buffer_on (f);
goto XI_OTHER;
}
@ -22592,9 +22707,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
tab_bar_arg = handle_tab_bar_click
(f, x, y, xev->evtype == XI_ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, bv.state));
{
tab_bar_arg = handle_tab_bar_click
(f, x, y, xev->evtype == XI_ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, bv.state));
x_flush_dirty_back_buffer_on (f);
}
}
#if ! defined (USE_GTK)
@ -22619,10 +22737,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| f->last_tool_bar_item != -1));
if (tool_bar_p && xev->detail < 4)
handle_tool_bar_click_with_device
(f, x, y, xev->evtype == XI_ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, bv.state),
source ? source->name : Qt);
{
handle_tool_bar_click_with_device
(f, x, y, xev->evtype == XI_ButtonPress,
x_x_to_emacs_modifiers (dpyinfo, bv.state),
source ? source->name : Qt);
x_flush_dirty_back_buffer_on (f);
}
}
#endif /* !USE_GTK */
@ -22919,8 +23040,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
)
{
mouse_frame = hlinfo->mouse_face_mouse_frame;
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
if (mouse_frame)
x_flush_dirty_back_buffer_on (mouse_frame);
}
if (f != 0)
@ -23299,7 +23425,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
/* Handle all disabled devices now, to prevent
things happening out-of-order later. */
if (ndevices)
if (n_disabled)
{
xi_disable_devices (dpyinfo, disabled, n_disabled);
n_disabled = 0;
@ -23704,12 +23830,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
| XkbModifierMapMask
| XkbVirtualModsMask),
dpyinfo->xkb_desc) == Success)
XkbGetNames (dpyinfo->display,
XkbGroupNamesMask | XkbVirtualModNamesMask,
XkbGetNames (dpyinfo->display, XkbAllNamesMask,
dpyinfo->xkb_desc);
else
{
XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True);
XkbFreeKeyboard (dpyinfo->xkb_desc,
XkbAllComponentsMask, True);
dpyinfo->xkb_desc = NULL;
}
}
@ -23723,8 +23849,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
XkbUseCoreKbd);
if (dpyinfo->xkb_desc)
XkbGetNames (dpyinfo->display,
XkbGroupNamesMask | XkbVirtualModNamesMask,
XkbGetNames (dpyinfo->display, XkbAllNamesMask,
dpyinfo->xkb_desc);
}
@ -24014,6 +24139,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (inev.ie.kind != NO_EVENT)
x_dnd_update_tooltip_now ();
}
#endif
#ifdef HAVE_XFIXES
if (dpyinfo->xfixes_supported_p
&& event->type == (dpyinfo->xfixes_event_base
+ XFixesSelectionNotify)
&& x_handle_selection_monitor_event (dpyinfo, event))
/* GTK 3 crashes if an XFixesSelectionNotify arrives with a
window other than the root window, because it wants to know
the screen in order to determine the compositing manager
selection name. (bug#58584) */
*finish = X_EVENT_DROP;
#endif
OTHER:
#ifdef USE_X_TOOLKIT
@ -24084,18 +24220,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
count++;
}
/* Sometimes event processing draws to either F or ANY outside
redisplay. To ensure that these changes become visible, draw
them here. */
#ifdef HAVE_XDBE
if (f)
flush_dirty_back_buffer_on (f);
if (any && any != f)
flush_dirty_back_buffer_on (any);
#endif
SAFE_FREE ();
return count;
}
@ -28527,6 +28651,27 @@ xi_check_toolkit (Display *display)
#endif
#ifdef HAVE_XFIXES
/* Create and return a special window for receiving events such as
selection notify events. The window is an 1x1 unmapped
override-redirect InputOnly window at -1, -1, which should prevent
it from doing anything. */
static Window
x_create_special_window (struct x_display_info *dpyinfo)
{
XSetWindowAttributes attrs;
attrs.override_redirect = True;
return XCreateWindow (dpyinfo->display, dpyinfo->root_window,
-1, -1, 1, 1, 0, CopyFromParent, InputOnly,
CopyFromParent, CWOverrideRedirect, &attrs);
}
#endif
/* Open a connection to X display DISPLAY_NAME, and return the
structure that describes the open display. If obtaining the XCB
connection or toolkit-specific display fails, return NULL. Signal
@ -28548,6 +28693,22 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
GdkDisplay *gdpy;
GdkScreen *gscr;
#endif
#ifdef HAVE_XFIXES
Lisp_Object tem, lisp_name;
int num_fast_selections;
Atom selection_name;
#ifdef USE_XCB
xcb_get_selection_owner_cookie_t *selection_cookies;
xcb_get_selection_owner_reply_t *selection_reply;
xcb_generic_error_t *selection_error;
#endif
#endif
int i;
USE_SAFE_ALLOCA;
/* Avoid warnings when SAFE_ALLOCA is not actually used. */
((void) SAFE_ALLOCA (0));
block_input ();
@ -28700,12 +28861,14 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#endif
unblock_input ();
SAFE_FREE ();
return 0;
}
#ifdef USE_XCB
xcb_conn = XGetXCBConnection (dpy);
if (xcb_conn == 0)
if (!xcb_conn)
{
#ifdef USE_GTK
xg_display_close (dpy);
@ -28718,6 +28881,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#endif /* ! USE_GTK */
unblock_input ();
SAFE_FREE ();
return 0;
}
#endif
@ -29270,8 +29435,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
XkbUseCoreKbd);
if (dpyinfo->xkb_desc)
XkbGetNames (dpyinfo->display,
XkbGroupNamesMask | XkbVirtualModNamesMask,
XkbGetNames (dpyinfo->display, XkbAllNamesMask,
dpyinfo->xkb_desc);
XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
@ -29281,9 +29445,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#endif
#ifdef HAVE_XFIXES
int xfixes_event_base, xfixes_error_base;
int xfixes_error_base;
dpyinfo->xfixes_supported_p
= XFixesQueryExtension (dpyinfo->display, &xfixes_event_base,
= XFixesQueryExtension (dpyinfo->display,
&dpyinfo->xfixes_event_base,
&xfixes_error_base);
if (dpyinfo->xfixes_supported_p)
@ -29334,7 +29499,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
XScreenNumberOfScreen (dpyinfo->screen));
{
int i;
enum { atom_count = ARRAYELTS (x_atom_refs) };
/* 1 for _XSETTINGS_SN. */
enum { total_atom_count = 2 + atom_count };
@ -29502,8 +29666,100 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->protected_windows_max = 256;
#endif
#ifdef HAVE_XFIXES
/* Initialize selection tracking for the selections in
x-fast-selection-list. */
if (CONSP (Vx_fast_selection_list)
&& dpyinfo->xfixes_supported_p
&& dpyinfo->xfixes_major >= 1)
{
num_fast_selections = 0;
tem = Vx_fast_selection_list;
FOR_EACH_TAIL_SAFE (tem)
{
if (!SYMBOLP (XCAR (tem)))
continue;
num_fast_selections++;
}
dpyinfo->n_monitored_selections = num_fast_selections;
dpyinfo->selection_tracking_window
= x_create_special_window (dpyinfo);
dpyinfo->monitored_selections
= xmalloc (num_fast_selections
* sizeof *dpyinfo->monitored_selections);
num_fast_selections = 0;
tem = Vx_fast_selection_list;
FOR_EACH_TAIL_SAFE (tem)
{
lisp_name = XCAR (tem);
if (!SYMBOLP (lisp_name))
continue;
selection_name = symbol_to_x_atom (dpyinfo, lisp_name);
dpyinfo->monitored_selections[num_fast_selections++].name
= selection_name;
dpyinfo->monitored_selections[num_fast_selections - 1].owner
= X_INVALID_WINDOW;
/* Select for selection input. */
XFixesSelectSelectionInput (dpyinfo->display,
dpyinfo->selection_tracking_window,
selection_name,
(XFixesSetSelectionOwnerNotifyMask
| XFixesSetSelectionOwnerNotifyMask
| XFixesSelectionClientCloseNotifyMask));
}
#ifdef USE_XCB
selection_cookies = SAFE_ALLOCA (sizeof *selection_cookies
* num_fast_selections);
#endif
/* Now, ask for the current owners of all those selections. */
for (i = 0; i < num_fast_selections; ++i)
{
#ifdef USE_XCB
selection_cookies[i]
= xcb_get_selection_owner (dpyinfo->xcb_connection,
dpyinfo->monitored_selections[i].name);
#else
dpyinfo->monitored_selections[i].owner
= XGetSelectionOwner (dpyinfo->display,
dpyinfo->monitored_selections[i].name);
#endif
}
#ifdef USE_XCB
for (i = 0; i < num_fast_selections; ++i)
{
selection_reply
= xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
selection_cookies[i],
&selection_error);
if (selection_reply)
{
dpyinfo->monitored_selections[i].owner
= selection_reply->owner;
free (selection_reply);
}
else if (selection_error)
free (selection_error);
}
#endif
}
#endif
unblock_input ();
SAFE_FREE ();
return dpyinfo;
}
@ -29639,6 +29895,10 @@ x_delete_display (struct x_display_info *dpyinfo)
xfree (dpyinfo->x_id_name);
xfree (dpyinfo->x_dnd_atoms);
xfree (dpyinfo->color_cells);
#ifdef HAVE_XFIXES
if (dpyinfo->monitored_selections)
xfree (dpyinfo->monitored_selections);
#endif
#ifdef USE_TOOLKIT_SCROLL_BARS
xfree (dpyinfo->protected_windows);
#endif
@ -30606,4 +30866,17 @@ It should accept a single argument, a string describing the locale of
the input method, and return a coding system that can decode keyboard
input generated by said input method. */);
Vx_input_coding_function = Qnil;
DEFVAR_LISP ("x-fast-selection-list", Vx_fast_selection_list,
doc: /* List of selections for which `x-selection-exists-p' should be fast.
List of selection names as atoms that will be monitored by Emacs for
ownership changes when the X server supports the XFIXES extension.
The result of the monitoring is then used by `x-selection-exists-p' to
avoid a server round trip, which is important as it is called while
updating the tool bar. The value of this variable is only read upon
connection setup. */);
/* The default value of this variable is chosen so that updating the
tool bar does not require a call to _XReply. */
Vx_fast_selection_list = list1 (QCLIPBOARD);
}

View file

@ -308,6 +308,22 @@ struct x_failable_request
unsigned long end;
};
#ifdef HAVE_XFIXES
struct x_monitored_selection
{
/* The name of the selection. */
Atom name;
/* The current owner of the selection. */
Window owner;
};
/* An invalid window. */
#define X_INVALID_WINDOW 0xffffffff
#endif
/* For each X display, we have a structure that records
information about it. */
@ -778,6 +794,7 @@ struct x_display_info
bool xfixes_supported_p;
int xfixes_major;
int xfixes_minor;
int xfixes_event_base;
#endif
#ifdef HAVE_XSYNC
@ -828,6 +845,17 @@ struct x_display_info
/* Pointer to the next request in `failable_requests'. */
struct x_failable_request *next_failable_request;
#ifdef HAVE_XFIXES
/* Array of selections being monitored and their owners. */
struct x_monitored_selection *monitored_selections;
/* Window used to monitor those selections. */
Window selection_tracking_window;
/* The number of those selections. */
int n_monitored_selections;
#endif
/* The pending drag-and-drop time for middle-click based
drag-and-drop emulation. */
Time pending_dnd_time;
@ -916,11 +944,6 @@ struct x_output
Picture picture;
#endif
/* Flag that indicates whether we've modified the back buffer and
need to publish our modifications to the front buffer at a
convenient time. */
bool need_buffer_flip;
/* The X window used for the bitmap icon;
or 0 if we don't have a bitmap icon. */
Window icon_desc;
@ -1091,6 +1114,18 @@ struct x_output
and inactive states. */
bool_bf alpha_identical_p : 1;
#ifdef HAVE_XDBE
/* Flag that indicates whether we've modified the back buffer and
need to publish our modifications to the front buffer at a
convenient time. */
bool_bf need_buffer_flip : 1;
/* Flag that indicates whether or not the frame contents are
complete and can be safely flushed while handling async
input. */
bool_bf complete : 1;
#endif
#ifdef HAVE_X_I18N
/* Input context (currently, this means Compose key handler setup). */
XIC xic;
@ -1248,6 +1283,10 @@ extern void x_mark_frame_dirty (struct frame *f);
/* Return the need-buffer-flip flag for frame F. */
#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
/* Return whether or not the frame F has been completely drawn. Used
while handling async input. */
#define FRAME_X_COMPLETE_P(f) ((f)->output_data.x->complete)
#endif
/* Return the outermost X window associated with the frame F. */
@ -1645,6 +1684,10 @@ extern void x_cr_draw_frame (cairo_t *, struct frame *);
extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
#endif
#ifdef HAVE_XFIXES
extern Window x_find_selection_owner (struct x_display_info *, Atom);
#endif
#ifdef HAVE_XRENDER
extern void x_xrender_color_from_gc_background (struct frame *, GC,
XRenderColor *, bool);
@ -1653,6 +1696,8 @@ extern void x_xr_apply_ext_clip (struct frame *, GC);
extern void x_xr_reset_ext_clip (struct frame *);
#endif
extern void x_translate_coordinates_to_root (struct frame *, int, int,
int *, int *);
extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *,
int *, int *, int *, unsigned int *);

View file

@ -297,5 +297,27 @@ Edebug symbols (Bug#42672)."
(intern "cl-defgeneric/edebug/method/2 (number)")
'cl-defgeneric/edebug/method/2))))))
(cl-defgeneric cl-generic-tests--acc (x &optional y)
(declare (advertised-calling-convention (x) "671.2")))
(cl-defmethod cl-generic-tests--acc ((x float)) (+ x 5.0))
(ert-deftest cl-generic-tests--advertised-calling-convention-bug58563 ()
(should (equal (get-advertised-calling-convention
(indirect-function 'cl-generic-tests--acc))
'(x)))
(should
(condition-case err
(let ((lexical-binding t)
(byte-compile-debug t)
(byte-compile-error-on-warn t))
(byte-compile '(cl-defmethod cl-generic-tests--acc ((x list))
(declare (advertised-calling-convention (y) "1.1"))
(cons x '(5 5 5 5 5))))
nil)
(error
(and (eq 'error (car err))
(string-match "Stray.*declare" (cadr err)))))))
(provide 'cl-generic-tests)
;;; cl-generic-tests.el ends here

View file

@ -0,0 +1,77 @@
;;; comp-tests.el --- Tests for comp.el -*- lexical-binding:t -*-
;; Copyright (C) 2022 Free Software Foundation, Inc.
;; 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:
(require 'ert)
(require 'ert-x)
(require 'comp)
(defvar comp-native-version-dir)
(defvar native-comp-eln-load-path)
(defmacro with-test-native-compile-prune-cache (&rest body)
(declare (indent 0) (debug t))
`(ert-with-temp-directory testdir
(setq testdir (expand-file-name "eln-cache" testdir))
(make-directory testdir)
(let* ((c1 (expand-file-name "29.0.50-cur" testdir))
(c2 (expand-file-name "29.0.50-old" testdir))
(native-comp-eln-load-path (list testdir))
(comp-native-version-dir "29.0.50-cur"))
(dolist (d (list c1 c2))
(make-directory d)
(with-temp-file (expand-file-name "some.eln" d) (insert "foo"))
(with-temp-file (expand-file-name "some.eln.tmp" d) (insert "foo")))
,@body)))
(ert-deftest test-native-compile-prune-cache ()
(skip-unless (featurep 'native-compile))
(with-test-native-compile-prune-cache
(native-compile-prune-cache)
(should (file-directory-p c1))
(should (file-regular-p (expand-file-name "some.eln" c1)))
(should (file-regular-p (expand-file-name "some.eln.tmp" c1)))
(should-not (file-directory-p c2))
(should-not (file-regular-p (expand-file-name "some.eln" c2)))
(should-not (file-regular-p (expand-file-name "some.eln.tmp" c2)))))
(ert-deftest test-native-compile-prune-cache/delete-only-eln ()
(skip-unless (featurep 'native-compile))
(with-test-native-compile-prune-cache
(with-temp-file (expand-file-name "keep1.txt" c1) (insert "foo"))
(with-temp-file (expand-file-name "keep2.txt" c2) (insert "foo"))
(native-compile-prune-cache)
(should (file-regular-p (expand-file-name "keep1.txt" c1)))
(should (file-regular-p (expand-file-name "keep2.txt" c2)))))
(ert-deftest test-native-compile-prune-cache/dont-delete-in-parent-of-cache ()
(skip-unless (featurep 'native-compile))
(with-test-native-compile-prune-cache
(let ((f1 (expand-file-name "../some.eln" testdir))
(f2 (expand-file-name "some.eln" testdir)))
(with-temp-file f1 (insert "foo"))
(with-temp-file f2 (insert "foo"))
(native-compile-prune-cache)
(should (file-regular-p f1))
(should (file-regular-p f2)))))
;;; comp-tests.el ends here

View file

@ -0,0 +1,76 @@
;;; esh-ext-tests.el --- esh-ext test suite -*- lexical-binding:t -*-
;; Copyright (C) 2022 Free Software Foundation, Inc.
;; 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:
;; Tests for Eshell's external command handling.
;;; Code:
(require 'ert)
(require 'esh-mode)
(require 'esh-ext)
(require 'eshell)
(require 'eshell-tests-helpers
(expand-file-name "eshell-tests-helpers"
(file-name-directory (or load-file-name
default-directory))))
;;; Tests:
(ert-deftest esh-ext-test/addpath/end ()
"Test that \"addpath\" adds paths to the end of $PATH."
(with-temp-eshell
(let ((eshell-path-env-list '("/some/path" "/other/path"))
(expected-path (string-join '("/some/path" "/other/path" "/new/path"
"/new/path2")
(path-separator))))
(eshell-match-command-output "addpath /new/path /new/path2"
(concat expected-path "\n"))
(eshell-match-command-output "echo $PATH"
(concat expected-path "\n")))))
(ert-deftest esh-ext-test/addpath/begin ()
"Test that \"addpath -b\" adds paths to the beginning of $PATH."
(with-temp-eshell
(let ((eshell-path-env-list '("/some/path" "/other/path"))
(expected-path (string-join '("/new/path" "/new/path2" "/some/path"
"/other/path")
(path-separator))))
(eshell-match-command-output "addpath -b /new/path /new/path2"
(concat expected-path "\n"))
(eshell-match-command-output "echo $PATH"
(concat expected-path "\n")))))
(ert-deftest esh-ext-test/addpath/set-locally ()
"Test adding to the path temporarily in a subcommand."
(let* ((eshell-path-env-list '("/some/path" "/other/path"))
(original-path (string-join eshell-path-env-list (path-separator)))
(local-path (string-join (append eshell-path-env-list '("/new/path"))
(path-separator))))
(with-temp-eshell
(eshell-match-command-output
"{ addpath /new/path; env }"
(format "PATH=%s\n" (regexp-quote local-path)))
;; After the last command, the previous $PATH value should be restored.
(eshell-match-command-output "echo $PATH"
(concat original-path "\n")))))
;; esh-ext-tests.el ends here

View file

@ -23,8 +23,10 @@
;;; Code:
(require 'tramp)
(require 'ert)
(require 'esh-mode)
(require 'esh-var)
(require 'eshell)
(require 'eshell-tests-helpers
@ -439,6 +441,150 @@ inside double-quotes"
(eshell-command-result-equal "echo \"${echo \\\"000 010 020\\\"}[0]\""
"000"))
;; Variable-related commands
(ert-deftest esh-var-test/set/env-var ()
"Test that `set' with a string variable name sets an environment variable."
(with-temp-eshell
(eshell-match-command-output "set VAR hello" "hello\n")
(should (equal (getenv "VAR") "hello")))
(should-not (equal (getenv "VAR") "hello")))
(ert-deftest esh-var-test/set/symbol ()
"Test that `set' with a symbol variable name sets a Lisp variable."
(let (eshell-test-value)
(eshell-command-result-equal "set #'eshell-test-value hello"
"hello")
(should (equal eshell-test-value "hello"))))
(ert-deftest esh-var-test/unset/env-var ()
"Test that `unset' with a string variable name unsets an env var."
(let ((process-environment (cons "VAR=value" process-environment)))
(with-temp-eshell
(eshell-match-command-output "unset VAR" "\\`\\'")
(should (equal (getenv "VAR") nil)))
(should (equal (getenv "VAR") "value"))))
(ert-deftest esh-var-test/unset/symbol ()
"Test that `unset' with a symbol variable name unsets a Lisp variable."
(let ((eshell-test-value "value"))
(eshell-command-result-equal "unset #'eshell-test-value" nil)
(should (equal eshell-test-value nil))))
(ert-deftest esh-var-test/setq ()
"Test that `setq' sets Lisp variables."
(let (eshell-test-value)
(eshell-command-result-equal "setq eshell-test-value hello"
"hello")
(should (equal eshell-test-value "hello"))))
(ert-deftest esh-var-test/export ()
"Test that `export' sets environment variables."
(with-temp-eshell
(eshell-match-command-output "export VAR=hello" "\\`\\'")
(should (equal (getenv "VAR") "hello"))))
(ert-deftest esh-var-test/local-variables ()
"Test that \"VAR=value command\" temporarily sets variables."
(with-temp-eshell
(push "VAR=value" process-environment)
(eshell-match-command-output "VAR=hello env" "VAR=hello\n")
(should (equal (getenv "VAR") "value"))))
;; Variable aliases
(ert-deftest esh-var-test/alias/function ()
"Test using a variable alias defined as a function."
(with-temp-eshell
(push `("ALIAS" ,(lambda () "value") nil t) eshell-variable-aliases-list)
(eshell-match-command-output "echo $ALIAS" "value\n")
(eshell-match-command-output "set ALIAS hello"
"Variable `ALIAS' is not settable\n"
nil t)))
(ert-deftest esh-var-test/alias/function-pair ()
"Test using a variable alias defined as a pair of getter/setter functions."
(with-temp-eshell
(let ((eshell-test-value "value"))
(push `("ALIAS" (,(lambda () eshell-test-value)
. (lambda (_ value)
(setq eshell-test-value (upcase value))))
nil t)
eshell-variable-aliases-list)
(eshell-match-command-output "echo $ALIAS" "value\n")
(eshell-match-command-output "set ALIAS hello" "HELLO\n")
(should (equal eshell-test-value "HELLO")))))
(ert-deftest esh-var-test/alias/string ()
"Test using a variable alias defined as a string.
This should get/set the aliased environment variable."
(with-temp-eshell
(let ((eshell-test-value "lisp-value"))
(push "eshell-test-value=env-value" process-environment)
(push `("ALIAS" "eshell-test-value") eshell-variable-aliases-list)
(eshell-match-command-output "echo $ALIAS" "env-value\n")
(eshell-match-command-output "set ALIAS hello" "hello\n")
(should (equal (getenv "eshell-test-value") "hello"))
(should (equal eshell-test-value "lisp-value")))))
(ert-deftest esh-var-test/alias/string/prefer-lisp ()
"Test using a variable alias defined as a string.
This sets `eshell-prefer-lisp-variables' to t and should get/set
the aliased Lisp variable."
(with-temp-eshell
(let ((eshell-test-value "lisp-value")
(eshell-prefer-lisp-variables t))
(push "eshell-test-value=env-value" process-environment)
(push `("ALIAS" "eshell-test-value") eshell-variable-aliases-list)
(eshell-match-command-output "echo $ALIAS" "lisp-value\n")
(eshell-match-command-output "set ALIAS hello" "hello\n")
(should (equal (car process-environment) "eshell-test-value=env-value"))
(should (equal eshell-test-value "hello")))))
(ert-deftest esh-var-test/alias/symbol ()
"Test using a variable alias defined as a symbol.
This should get/set the value bound to the symbol."
(with-temp-eshell
(let ((eshell-test-value "value"))
(push '("ALIAS" eshell-test-value) eshell-variable-aliases-list)
(eshell-match-command-output "echo $ALIAS" "value\n")
(eshell-match-command-output "set ALIAS hello" "hello\n")
(should (equal eshell-test-value "hello")))))
(ert-deftest esh-var-test/alias/symbol-pair ()
"Test using a variable alias defined as a pair of symbols.
This should get the value bound to the symbol, but fail to set
it, since the setter is nil."
(with-temp-eshell
(let ((eshell-test-value "value"))
(push '("ALIAS" (eshell-test-value . nil)) eshell-variable-aliases-list)
(eshell-match-command-output "echo $ALIAS" "value\n")
(eshell-match-command-output "set ALIAS hello"
"Variable `ALIAS' is not settable\n"
nil t))))
(ert-deftest esh-var-test/alias/export ()
"Test that `export' properly sets variable aliases."
(with-temp-eshell
(let ((eshell-test-value "value"))
(push `("ALIAS" (,(lambda () eshell-test-value)
. (lambda (_ value) (setq eshell-test-value value)))
nil t)
eshell-variable-aliases-list)
(eshell-match-command-output "export ALIAS=hello" "\\`\\'")
(should (equal eshell-test-value "hello")))))
(ert-deftest esh-var-test/alias/local-variables ()
"Test that \"VAR=value cmd\" temporarily sets read-only variable aliases."
(with-temp-eshell
(let ((eshell-test-value "value"))
(push `("ALIAS" ,(lambda () eshell-test-value) t t)
eshell-variable-aliases-list)
(eshell-match-command-output "ALIAS=hello env" "ALIAS=hello\n")
(should (equal eshell-test-value "value")))))
;; Built-in variables
@ -465,6 +611,65 @@ inside double-quotes"
(eshell-match-command-output "echo $INSIDE_EMACS[, 1]"
"eshell")))
(ert-deftest esh-var-test/path-var/local-directory ()
"Test using $PATH in a local directory."
(let ((expected-path (string-join (eshell-get-path t) (path-separator))))
(with-temp-eshell
(eshell-match-command-output "echo $PATH" (regexp-quote expected-path)))))
(ert-deftest esh-var-test/path-var/remote-directory ()
"Test using $PATH in a remote directory."
(skip-unless (eshell-tests-remote-accessible-p))
(let* ((default-directory ert-remote-temporary-file-directory)
(expected-path (string-join (eshell-get-path t) (path-separator))))
(with-temp-eshell
(eshell-match-command-output "echo $PATH" (regexp-quote expected-path)))))
(ert-deftest esh-var-test/path-var/set ()
"Test setting $PATH."
(let* ((path-to-set-list '("/some/path" "/other/path"))
(path-to-set (string-join path-to-set-list (path-separator))))
(with-temp-eshell
(eshell-match-command-output (concat "set PATH " path-to-set)
(concat path-to-set "\n"))
(eshell-match-command-output "echo $PATH" (concat path-to-set "\n"))
(should (equal (eshell-get-path t) path-to-set-list)))))
(ert-deftest esh-var-test/path-var/set-locally ()
"Test setting $PATH temporarily for a single command."
(let* ((path-to-set-list '("/some/path" "/other/path"))
(path-to-set (string-join path-to-set-list (path-separator))))
(with-temp-eshell
(eshell-match-command-output (concat "set PATH " path-to-set)
(concat path-to-set "\n"))
(eshell-match-command-output "PATH=/local/path env"
"PATH=/local/path\n")
;; After the last command, the previous $PATH value should be restored.
(eshell-match-command-output "echo $PATH" (concat path-to-set "\n"))
(should (equal (eshell-get-path t) path-to-set-list)))))
(ert-deftest esh-var-test/path-var/preserve-across-hosts ()
"Test that $PATH can be set independently on multiple hosts."
(let ((local-directory default-directory)
local-path remote-path)
(with-temp-eshell
;; Set the $PATH on localhost.
(eshell-insert-command "set PATH /local/path")
(setq local-path (eshell-last-output))
;; `cd' to a remote host and set the $PATH there too.
(eshell-insert-command
(format "cd %s" ert-remote-temporary-file-directory))
(eshell-insert-command "set PATH /remote/path")
(setq remote-path (eshell-last-output))
;; Return to localhost and check that $PATH is the value we set
;; originally.
(eshell-insert-command (format "cd %s" local-directory))
(eshell-match-command-output "echo $PATH" (regexp-quote local-path))
;; ... and do the same for the remote host.
(eshell-insert-command
(format "cd %s" ert-remote-temporary-file-directory))
(eshell-match-command-output "echo $PATH" (regexp-quote remote-path)))))
(ert-deftest esh-var-test/last-status-var-lisp-command ()
"Test using the \"last exit status\" ($?) variable with a Lisp command"
(with-temp-eshell
@ -472,9 +677,8 @@ inside double-quotes"
"t\n0\n")
(eshell-match-command-output "zerop 1; echo $?"
"0\n")
(let ((debug-on-error nil))
(eshell-match-command-output "zerop foo; echo $?"
"1\n"))))
(eshell-match-command-output "zerop foo; echo $?"
"1\n" nil t)))
(ert-deftest esh-var-test/last-status-var-lisp-form ()
"Test using the \"last exit status\" ($?) variable with a Lisp form"
@ -484,9 +688,8 @@ inside double-quotes"
"t\n0\n")
(eshell-match-command-output "(zerop 1); echo $?"
"2\n")
(let ((debug-on-error nil))
(eshell-match-command-output "(zerop \"foo\"); echo $?"
"1\n")))))
(eshell-match-command-output "(zerop \"foo\"); echo $?"
"1\n" nil t))))
(ert-deftest esh-var-test/last-status-var-lisp-form-2 ()
"Test using the \"last exit status\" ($?) variable with a Lisp form.
@ -497,9 +700,8 @@ This tests when `eshell-lisp-form-nil-is-failure' is nil."
"0\n")
(eshell-match-command-output "(zerop 0); echo $?"
"0\n")
(let ((debug-on-error nil))
(eshell-match-command-output "(zerop \"foo\"); echo $?"
"1\n")))))
(eshell-match-command-output "(zerop \"foo\"); echo $?"
"1\n" nil t))))
(ert-deftest esh-var-test/last-status-var-ext-cmd ()
"Test using the \"last exit status\" ($?) variable with an external command"

View file

@ -31,11 +31,22 @@
(require 'eshell)
(defvar eshell-history-file-name nil)
(defvar eshell-last-dir-ring-file-name nil)
(defvar eshell-test--max-subprocess-time 5
"The maximum amount of time to wait for a subprocess to finish, in seconds.
See `eshell-wait-for-subprocess'.")
(defun eshell-tests-remote-accessible-p ()
"Return if a test involving remote files can proceed.
If using this function, be sure to load `tramp' near the
beginning of the test file."
(ignore-errors
(and
(file-remote-p ert-remote-temporary-file-directory)
(file-directory-p ert-remote-temporary-file-directory)
(file-writable-p ert-remote-temporary-file-directory))))
(defmacro with-temp-eshell (&rest body)
"Evaluate BODY in a temporary Eshell buffer."
`(save-current-buffer
@ -44,6 +55,7 @@ See `eshell-wait-for-subprocess'.")
;; back on $HISTFILE.
(process-environment (cons "HISTFILE" process-environment))
(eshell-history-file-name nil)
(eshell-last-dir-ring-file-name nil)
(eshell-buffer (eshell t)))
(unwind-protect
(with-current-buffer eshell-buffer
@ -83,26 +95,39 @@ After inserting, call FUNC. If FUNC is nil, instead call
(insert-and-inherit command)
(funcall (or func 'eshell-send-input)))
(defun eshell-last-input ()
"Return the input of the last Eshell command."
(buffer-substring-no-properties
eshell-last-input-start eshell-last-input-end))
(defun eshell-last-output ()
"Return the output of the last Eshell command."
(buffer-substring-no-properties
(eshell-beginning-of-output) (eshell-end-of-output)))
(defun eshell-match-output (regexp)
"Test whether the output of the last command matches REGEXP."
(string-match-p
regexp (buffer-substring-no-properties
(eshell-beginning-of-output) (eshell-end-of-output))))
(string-match-p regexp (eshell-last-output)))
(defun eshell-match-output--explainer (regexp)
"Explain the result of `eshell-match-output'."
`(mismatched-output
(command ,(buffer-substring-no-properties
eshell-last-input-start eshell-last-input-end))
(output ,(buffer-substring-no-properties
(eshell-beginning-of-output) (eshell-end-of-output)))
(command ,(eshell-last-input))
(output ,(eshell-last-output))
(regexp ,regexp)))
(put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer)
(defun eshell-match-command-output (command regexp &optional func)
"Insert a COMMAND at the end of the buffer and match the output with REGEXP."
(eshell-insert-command command func)
(defun eshell-match-command-output (command regexp &optional func
ignore-errors)
"Insert a COMMAND at the end of the buffer and match the output with REGEXP.
FUNC is the function to call after inserting the text (see
`eshell-insert-command').
If IGNORE-ERRORS is non-nil, ignore any errors signaled when
inserting the command."
(let ((debug-on-error (and (not ignore-errors) debug-on-error)))
(eshell-insert-command command func))
(eshell-wait-for-subprocess)
(should (eshell-match-output regexp)))

View file

@ -23,6 +23,7 @@
(require 'ert)
(require 'files-x)
(require 'tramp-integration)
(defconst files-x-test--variables1
'((remote-shell-file-name . "/bin/bash")
@ -35,16 +36,20 @@
'((remote-null-device . "/dev/null")))
(defconst files-x-test--variables4
'((remote-null-device . "null")))
(defconst files-x-test--variables5
'((remote-lazy-var . nil)
(remote-null-device . "/dev/null")))
(defvar remote-null-device)
(defvar remote-lazy-var nil)
(put 'remote-shell-file-name 'safe-local-variable #'identity)
(put 'remote-shell-command-switch 'safe-local-variable #'identity)
(put 'remote-shell-interactive-switch 'safe-local-variable #'identity)
(put 'remote-shell-login-switch 'safe-local-variable #'identity)
(put 'remote-null-device 'safe-local-variable #'identity)
(defconst files-x-test--application '(:application 'my-application))
(defconst files-x-test--application '(:application my-application))
(defconst files-x-test--another-application
'(:application 'another-application))
'(:application another-application))
(defconst files-x-test--protocol '(:protocol "my-protocol"))
(defconst files-x-test--user '(:user "my-user"))
(defconst files-x-test--machine '(:machine "my-machine"))
@ -91,6 +96,28 @@
(connection-local-get-profile-variables 'remote-nullfile)
files-x-test--variables4))))
(ert-deftest files-x-test-connection-local-update-profile-variables ()
"Test updating connection-local profile variables."
;; Declare (PROFILE VARIABLES) objects.
(let (connection-local-profile-alist connection-local-criteria-alist)
(connection-local-set-profile-variables
'remote-bash (copy-alist files-x-test--variables1))
(should
(equal
(connection-local-get-profile-variables 'remote-bash)
files-x-test--variables1))
;; Updating overwrites only the values specified in this call, but
;; retains all the other values from previous calls.
(connection-local-update-profile-variables
'remote-bash files-x-test--variables2)
(should
(equal
(connection-local-get-profile-variables 'remote-bash)
(cons (car files-x-test--variables2)
(cdr files-x-test--variables1))))))
(ert-deftest files-x-test-connection-local-set-profiles ()
"Test setting connection-local profiles."
@ -233,9 +260,12 @@
(nreverse (copy-tree files-x-test--variables2)))))
;; The variables exist also as local variables.
(should (local-variable-p 'remote-shell-file-name))
(should (local-variable-p 'remote-null-device))
;; The proper variable value is set.
(should
(string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))))
(string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
(should
(string-equal (symbol-value 'remote-null-device) "/dev/null"))))
;; The third test case. Both criteria `files-x-test--criteria1'
;; and `files-x-test--criteria2' apply, but there are no double
@ -274,13 +304,11 @@
(should-not (local-variable-p 'remote-shell-file-name))
(should-not (boundp 'remote-shell-file-name))))))
(defvar tramp-connection-local-default-shell-variables)
(defvar tramp-connection-local-default-system-variables)
(ert-deftest files-x-test-with-connection-local-variables ()
"Test setting connection-local variables."
(let (connection-local-profile-alist connection-local-criteria-alist)
(let ((connection-local-profile-alist connection-local-profile-alist)
(connection-local-criteria-alist connection-local-criteria-alist))
(connection-local-set-profile-variables
'remote-bash files-x-test--variables1)
(connection-local-set-profile-variables
@ -291,29 +319,6 @@
(connection-local-set-profiles
nil 'remote-ksh 'remote-nullfile)
(with-temp-buffer
(let ((enable-connection-local-variables t))
(hack-connection-local-variables-apply nil)
;; All connection-local variables are set. They apply in
;; reverse order in `connection-local-variables-alist'.
(should
(equal connection-local-variables-alist
(append
(nreverse (copy-tree files-x-test--variables3))
(nreverse (copy-tree files-x-test--variables2)))))
;; The variables exist also as local variables.
(should (local-variable-p 'remote-shell-file-name))
(should (local-variable-p 'remote-null-device))
;; The proper variable values are set.
(should
(string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
(should
(string-equal (symbol-value 'remote-null-device) "/dev/null"))
;; A candidate connection-local variable is not bound yet.
(should-not (local-variable-p 'remote-shell-command-switch))))
(with-temp-buffer
;; Use the macro. We need a remote `default-directory'.
(let ((enable-connection-local-variables t)
@ -331,18 +336,18 @@
(with-connection-local-variables
;; All connection-local variables are set. They apply in
;; reverse order in `connection-local-variables-alist'.
;; Since we ha a remote default directory, Tramp's settings
;; Since we have a remote default directory, Tramp's settings
;; are appended as well.
(should
(equal
connection-local-variables-alist
(append
(nreverse (copy-tree files-x-test--variables3))
(nreverse (copy-tree files-x-test--variables2))
(nreverse
(copy-tree tramp-connection-local-default-shell-variables))
(nreverse
(copy-tree tramp-connection-local-default-system-variables)))))
(copy-tree tramp-connection-local-default-system-variables))
(nreverse (copy-tree files-x-test--variables3))
(nreverse (copy-tree files-x-test--variables2)))))
;; The variables exist also as local variables.
(should (local-variable-p 'remote-shell-file-name))
(should (local-variable-p 'remote-null-device))
@ -352,15 +357,21 @@
(should
(string-equal (symbol-value 'remote-null-device) "/dev/null"))
;; Run another instance of `with-connection-local-variables'
;; with a different application.
(let ((connection-local-default-application (cadr files-x-test--application)))
(with-connection-local-variables
;; The proper variable values are set.
(should
(string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
(should
(string-equal (symbol-value 'remote-null-device) "/dev/null"))))
;; Run `with-connection-local-application-variables' to use a
;; different application.
(with-connection-local-application-variables
(cadr files-x-test--application)
(should
(equal
connection-local-variables-alist
(append
(nreverse (copy-tree files-x-test--variables3))
(nreverse (copy-tree files-x-test--variables1)))))
;; The proper variable values are set.
(should
(string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
(should
(string-equal (symbol-value 'remote-null-device) "/dev/null")))
;; The variable values are reset.
(should
(string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
@ -376,5 +387,60 @@
(should-not (boundp 'remote-shell-file-name))
(should (string-equal (symbol-value 'remote-null-device) "null"))))))
(defun files-x-test--get-lazy-var ()
"Get the connection-local value of `remote-lazy-var'.
If it's not initialized yet, initialize it."
(with-connection-local-application-variables
(cadr files-x-test--application)
(or remote-lazy-var
(setq-connection-local remote-lazy-var
(or (file-remote-p default-directory 'host)
"local")))))
(defun files-x-test--set-lazy-var (value)
"Set the connection-local value of `remote-lazy-var'"
(with-connection-local-application-variables
(cadr files-x-test--application)
(setq-connection-local remote-lazy-var value)))
(ert-deftest files-x-test-setq-connection-local ()
"Test dynamically setting connection local variables."
(let (connection-local-profile-alist connection-local-criteria-alist)
(connection-local-set-profile-variables
'remote-lazy files-x-test--variables5)
(connection-local-set-profiles
files-x-test--application
'remote-lazy)
;; Test the initial local value.
(should (equal (files-x-test--get-lazy-var) "local"))
;; Set the local value and make sure it retains the value we set.
(should (equal (files-x-test--set-lazy-var "here") "here"))
(should (equal (files-x-test--get-lazy-var) "here"))
(let ((default-directory "/method:host:"))
;; Test the initial remote value.
(should (equal (files-x-test--get-lazy-var) "host"))
;; Set the remote value and make sure it retains the value we set.
(should (equal (files-x-test--set-lazy-var "there") "there"))
(should (equal (files-x-test--get-lazy-var) "there"))
;; Set another connection-local variable.
(with-connection-local-application-variables
(cadr files-x-test--application)
(setq-connection-local remote-null-device "null")))
;; Make sure we get the local value we set above.
(should (equal (files-x-test--get-lazy-var) "here"))
(should-not (boundp 'remote-null-device))
;; Make sure we get the remote values we set above.
(let ((default-directory "/method:host:"))
(should (equal (files-x-test--get-lazy-var) "there"))
(with-connection-local-application-variables
(cadr files-x-test--application)
(should (equal remote-null-device "null"))))))
(provide 'files-x-tests)
;;; files-x-tests.el ends here

View file

@ -4396,7 +4396,41 @@ def foo():
(python-shell-interpreter "/some/path/to/bin/pypy"))
(should (python-shell-completion-native-interpreter-disabled-p))))
(ert-deftest python-shell-completion-1 ()
(ert-deftest python-shell-completion-at-point-1 ()
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
""
(python-shell-with-shell-buffer
(insert "import abc")
(comint-send-input)
(python-tests-shell-wait-for-prompt)
(insert "abc.")
(should (nth 2 (python-shell-completion-at-point)))
(end-of-line 0)
(should-not (nth 2 (python-shell-completion-at-point))))))
(ert-deftest python-shell-completion-at-point-native-1 ()
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
""
(python-shell-completion-native-turn-on)
(python-shell-with-shell-buffer
(insert "import abc")
(comint-send-input)
(python-tests-shell-wait-for-prompt)
(insert "abc.")
(should (nth 2 (python-shell-completion-at-point)))
(end-of-line 0)
(should-not (nth 2 (python-shell-completion-at-point))))))
;;; PDB Track integration
;;; Symbol completion
(ert-deftest python-completion-at-point-1 ()
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
"
@ -4411,7 +4445,7 @@ import abc
(insert "A")
(should (completion-at-point)))))
(ert-deftest python-shell-completion-2 ()
(ert-deftest python-completion-at-point-2 ()
"Should work regardless of the point in the Shell buffer."
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
@ -4427,7 +4461,24 @@ import abc
(insert "abc.")
(should (completion-at-point)))))
(ert-deftest python-shell-completion-native-1 ()
(ert-deftest python-completion-at-point-pdb-1 ()
"Should not complete PDB commands in Python buffer."
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
"
import pdb
pdb.set_trace()
print('Hello')
"
(let ((inhibit-message t))
(python-shell-send-buffer)
(python-tests-shell-wait-for-prompt)
(goto-char (point-max))
(insert "u")
(should-not (nth 2 (python-completion-at-point))))))
(ert-deftest python-completion-at-point-native-1 ()
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
"
@ -4443,7 +4494,7 @@ import abc
(insert "A")
(should (completion-at-point)))))
(ert-deftest python-shell-completion-native-2 ()
(ert-deftest python-completion-at-point-native-2 ()
"Should work regardless of the point in the Shell buffer."
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
@ -4460,7 +4511,7 @@ import abc
(insert "abc.")
(should (completion-at-point)))))
(ert-deftest python-shell-completion-native-with-ffap-1 ()
(ert-deftest python-completion-at-point-native-with-ffap-1 ()
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
"
@ -4476,7 +4527,7 @@ import abc
(python-ffap-module-path "abc.")
(should (completion-at-point)))))
(ert-deftest python-shell-completion-native-with-eldoc-1 ()
(ert-deftest python-completion-at-point-native-with-eldoc-1 ()
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-buffer-with-shell
"
@ -4492,13 +4543,6 @@ import abc
(python-eldoc-function)
(should (completion-at-point)))))
;;; PDB Track integration
;;; Symbol completion
;;; Fill paragraph

View file

@ -22,6 +22,7 @@
;;; Code:
(require 'cl-lib)
(require 'ert)
(ert-deftest fns-tests-identity ()
(let ((num 12345)) (should (eq (identity num) num)))
@ -29,9 +30,22 @@
(let ((lst '(11))) (should (eq (identity lst) lst))))
(ert-deftest fns-tests-random ()
(should (integerp (random)))
(should (>= (random 10) 0))
(should (< (random 10) 10)))
(unwind-protect
(progn
(should-error (random -1) :type 'args-out-of-range)
(should-error (random 0) :type 'args-out-of-range)
(should (integerp (random)))
(should (= (random 1) 0))
(should (>= (random 10) 0))
(should (< (random 10) 10))
(should (equal (random "seed") (random "seed")))
;; The probability of four calls being the same is low.
;; This makes sure that the value isn't constant.
(should (not (= (random t) (random t) (random t) (random t))))
;; Handle bignums.
(should (integerp (random (1+ most-positive-fixnum)))))
;; Reset the PRNG seed after testing.
(random t)))
(ert-deftest fns-tests-length ()
(should (= (length nil) 0))