Merge remote-tracking branch 'origin/master' into feature/package+vc
This commit is contained in:
commit
65fa87329c
61 changed files with 2138 additions and 724 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
54
etc/NEWS
54
etc/NEWS
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))))
|
||||
|
|
|
|||
|
|
@ -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\\)?\\'"))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
103
lisp/files-x.el
103
lisp/files-x.el
|
|
@ -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'."
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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-"))
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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))))
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
14
lisp/subr.el
14
lisp/subr.el
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
17
src/comp.c
17
src/comp.c
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
115
src/xfns.c
115
src/xfns.c
|
|
@ -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
|
||||
|
|
|
|||
45
src/xmenu.c
45
src/xmenu.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
379
src/xterm.c
379
src/xterm.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
55
src/xterm.h
55
src/xterm.h
|
|
@ -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 *);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
77
test/lisp/emacs-lisp/comp-tests.el
Normal file
77
test/lisp/emacs-lisp/comp-tests.el
Normal 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
|
||||
76
test/lisp/eshell/esh-ext-tests.el
Normal file
76
test/lisp/eshell/esh-ext-tests.el
Normal 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
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue