mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 20:41:23 +00:00
Merge branch 'master' into feature/igc3
This commit is contained in:
commit
6eec001187
109 changed files with 3714 additions and 2591 deletions
|
|
@ -868,13 +868,20 @@ otherwise stated, affects only the current Emacs session. The only
|
|||
way to alter the variable in future sessions is to put something in
|
||||
your initialization file (@pxref{Init File}).
|
||||
|
||||
If you're setting a customizable variable in your initialization
|
||||
file, and you don't want to use the Customize interface, you can use
|
||||
the @code{setopt} macro. For instance:
|
||||
|
||||
@findex setopt
|
||||
If you're setting a customizable variable, and you don't want to use
|
||||
the Customize interface, you can use the @code{setopt} macro. For
|
||||
instance:
|
||||
|
||||
@example
|
||||
(setopt fill-column 75)
|
||||
M-: (setopt fill-column 75) @key{RET}
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Or, if you want to do this in your initialization file:
|
||||
|
||||
@example
|
||||
(setopt fill-column 75)
|
||||
@end example
|
||||
|
||||
This works the same as @code{setq}, but if the variable has any
|
||||
|
|
@ -883,6 +890,34 @@ special setter functions, they will be run automatically when using
|
|||
non-customizable variables, but this is less efficient than using
|
||||
@code{setq}.
|
||||
|
||||
@findex setopt-local
|
||||
There is also a buffer-local version of @code{setopt}, called
|
||||
@code{setopt-local}, that you can use to set buffer specific values for
|
||||
customizable options, for example, in mode hooks (@pxref{Hooks}).
|
||||
|
||||
This works the same as @code{setq-local}, but if the variable has any
|
||||
special setter functions, they will be run automatically when using
|
||||
@code{setopt-local}. You can also use @code{setopt-local} on other,
|
||||
non-customizable variables, but this is less efficient than using
|
||||
@code{setq-local}.
|
||||
|
||||
If you want to change the value of a customizable variable only in
|
||||
your current buffer, you can use the @code{setopt-local} macro. For
|
||||
instance:
|
||||
|
||||
@example
|
||||
M-: (setopt-local fill-column 75) @key{RET}
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Or, if you want to do this in your initialization file, use the
|
||||
following inside a mode hook so this variable will be automatically
|
||||
customized in buffers of that mode (@pxref{Hooks}):
|
||||
|
||||
@example
|
||||
(setopt-local fill-column 75)
|
||||
@end example
|
||||
|
||||
@node Hooks
|
||||
@subsection Hooks
|
||||
@cindex hook
|
||||
|
|
@ -3262,7 +3297,7 @@ acquainted with conventions from other programs.
|
|||
The functionality enabled by the @code{newcomers-presets} theme will
|
||||
change between releases of Emacs. We may add new functionality, and
|
||||
also remove old functionality that we think has been superseded.
|
||||
Therefore, if you get used to the newcomers' presets, consider copying
|
||||
them into your own configuration and then disabling the theme again.
|
||||
You can use the command @code{copy-theme-options} (@pxref{Custom
|
||||
Themes}) to do this.
|
||||
Therefore, if you get used to the newcomers' presets, you should copy
|
||||
them into your own configuration and then disable the theme again. You
|
||||
can use the command @code{copy-theme-options} (@pxref{Custom Themes}) to
|
||||
do this.
|
||||
|
|
|
|||
|
|
@ -2764,10 +2764,10 @@ Table}.)
|
|||
@node Xref Commands
|
||||
@subsubsection Commands Available in the @file{*xref*} Buffer
|
||||
@cindex commands in @file{*xref*} buffers
|
||||
@cindex XREF mode
|
||||
@cindex Xref mode
|
||||
|
||||
The following commands are provided in the @file{*xref*} buffer by
|
||||
the special XREF mode:
|
||||
the special Xref mode:
|
||||
|
||||
@table @kbd
|
||||
@item @key{RET}
|
||||
|
|
@ -2880,7 +2880,7 @@ prompt always, customize the value of the variable
|
|||
to prompt only if there's no usable identifier at point.) The command
|
||||
then presents the @file{*xref*} buffer with all the references to the
|
||||
identifier, showing the file name and the line where the identifier is
|
||||
referenced. The XREF mode commands are available in this buffer, see
|
||||
referenced. The Xref mode commands are available in this buffer, see
|
||||
@ref{Xref Commands}.
|
||||
|
||||
When invoked in a buffer whose major mode uses the @code{etags} backend,
|
||||
|
|
@ -2926,6 +2926,16 @@ matches of that regexp in the names of the identifiers with
|
|||
@code{xref-query-replace-in-results}, but is more convenient when you
|
||||
want to rename a single identifier specified by its name @var{from}.
|
||||
|
||||
@findex xref-change-to-xref-edit-mode
|
||||
@cindex Xref Edit mode
|
||||
@cindex mode, Xref Edit
|
||||
Typing @kbd{e} in the @file{*xref*} buffer makes the buffer writable
|
||||
and enters the Xref Edit mode. Similar to Occur Edit mode (@pxref{Other
|
||||
Repeating Search}), you can edit the matching lines reported by
|
||||
Xref backend and have those changes reflected in the buffer visiting the
|
||||
originating file. Type @kbd{C-c C-c} to leave the Xref Edit mode and
|
||||
return to the Xref mode.
|
||||
|
||||
@findex tags-search
|
||||
@kbd{M-x tags-search} reads a regexp using the minibuffer, then
|
||||
searches for matches in all the files in the selected tags table, one
|
||||
|
|
|
|||
|
|
@ -14660,9 +14660,9 @@ beginning of the file. The function definition looks like this:
|
|||
@smallexample
|
||||
@group
|
||||
(defun lengths-list-file (filename)
|
||||
"Return list of definitions' lengths within FILE.
|
||||
"Return list of definitions' lengths within the file named FILENAME.
|
||||
The returned list is a list of numbers.
|
||||
Each number is the number of words or
|
||||
Each number in the list is the number of words or
|
||||
symbols in one function definition."
|
||||
@end group
|
||||
@group
|
||||
|
|
@ -14683,10 +14683,10 @@ symbols in one function definition."
|
|||
@end smallexample
|
||||
|
||||
@noindent
|
||||
The function is passed one argument, the name of the file on which it
|
||||
will work. It has four lines of documentation, but no interactive
|
||||
specification. Since people worry that a computer is broken if they
|
||||
don't see anything going on, the first line of the body is a
|
||||
The function is passed one argument @var{filename}, the name of the file
|
||||
on which it will work. It has four lines of documentation, but no
|
||||
interactive specification. Since people worry that a computer is broken
|
||||
if they don't see anything going on, the first line of the body is a
|
||||
message.
|
||||
|
||||
The next line contains a @code{save-excursion} that returns Emacs's
|
||||
|
|
@ -14730,8 +14730,8 @@ definition and constructs a lengths' list containing the information.
|
|||
Emacs kills the buffer after working through it. This is to save
|
||||
space inside of Emacs. My version of GNU Emacs 19 contained over 300
|
||||
source files of interest; GNU Emacs 22 contains over a thousand source
|
||||
files. Another function will apply @code{lengths-list-file} to each
|
||||
of the files.
|
||||
files, and Emacs 30.2 more than 1600. Another function will apply
|
||||
@code{lengths-list-file} to each of the files.
|
||||
|
||||
Finally, the last expression within the @code{let} expression is the
|
||||
@code{lengths-list} variable; its value is returned as the value of
|
||||
|
|
@ -14744,13 +14744,13 @@ C-e} (@code{eval-last-sexp}).
|
|||
@c !!! 22.1.1 lisp sources location here
|
||||
@smallexample
|
||||
(lengths-list-file
|
||||
"/usr/local/share/emacs/22.1/lisp/emacs-lisp/debug.el")
|
||||
"/usr/local/share/emacs/30.2/lisp/emacs-lisp/debug.el")
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
You may need to change the pathname of the file; the one here is for
|
||||
GNU Emacs version 22.1. To change the expression, copy it to
|
||||
the @file{*scratch*} buffer and edit it.
|
||||
You may need to change the name of the file; the one here is for default
|
||||
installation tree of GNU Emacs version 30.2. To change the expression,
|
||||
copy it to the @file{*scratch*} buffer and edit it.
|
||||
|
||||
@need 1200
|
||||
@noindent
|
||||
|
|
@ -14768,10 +14768,11 @@ Then evaluate the @code{lengths-list-file} expression.)
|
|||
|
||||
@need 1200
|
||||
The lengths' list for @file{debug.el} takes less than a second to
|
||||
produce and looks like this in GNU Emacs 22:
|
||||
produce and looks like this in GNU Emacs 30.2:
|
||||
|
||||
@smallexample
|
||||
(83 113 105 144 289 22 30 97 48 89 25 52 52 88 28 29 77 49 43 290 232 587)
|
||||
(79 26 140 34 17 112 81 24 155 54 43 102 21 36 36 117 28 29 102 49 43
|
||||
208 101 28 22 728 15 27)
|
||||
@end smallexample
|
||||
|
||||
@need 1500
|
||||
|
|
|
|||
|
|
@ -372,12 +372,15 @@ added by calls to @code{custom-add-frequent-value} (see below).
|
|||
@item :set @var{setfunction}
|
||||
Specify @var{setfunction} as the way to change the value of this
|
||||
option when using the Customize interface. The function
|
||||
@var{setfunction} should take two arguments, a symbol (the option
|
||||
name) and the new value, and should do whatever is necessary to update
|
||||
@var{setfunction} should take two or three arguments, a symbol (the option
|
||||
name), the new value, and an optional @var{buffer-local} indicator.
|
||||
@var{setfunction} should do whatever is necessary to update
|
||||
the value properly for this option (which may not mean simply setting
|
||||
the option as a Lisp variable); preferably, though, it should not
|
||||
modify its value argument destructively. The default for
|
||||
@var{setfunction} is @code{set-default-toplevel-value}.
|
||||
modify its value argument destructively. If optional @var{buffer-local}
|
||||
is non-nil, the new value should be set buffer locally and not affect its
|
||||
global or default values. The default for @var{setfunction} is
|
||||
@code{set-default-toplevel-value}.
|
||||
|
||||
If defined, @var{setfunction} will also be called when evaluating a
|
||||
@code{defcustom} form with @kbd{C-M-x} in Emacs Lisp mode and when the
|
||||
|
|
@ -387,7 +390,7 @@ If defined, @var{setfunction} will also be called when evaluating a
|
|||
If you specify this keyword, the variable's documentation string
|
||||
should describe how to do the same job in hand-written Lisp code,
|
||||
either by invoking @var{setfunction} directly or by using
|
||||
@code{setopt}.
|
||||
@code{setopt} or @code{setopt-local}.
|
||||
|
||||
@kindex get@r{, @code{defcustom} keyword}
|
||||
@item :get @var{getfunction}
|
||||
|
|
|
|||
|
|
@ -1661,6 +1661,7 @@ Tips and Conventions
|
|||
* Compilation Tips:: Making compiled code run fast.
|
||||
* Warning Tips:: Turning off compiler warnings.
|
||||
* Documentation Tips:: Writing readable documentation strings.
|
||||
* Documentation Group Tips:: Writing useful documentation groups.
|
||||
* Comment Tips:: Conventions for writing comments.
|
||||
* Library Headers:: Standard headers for library packages.
|
||||
|
||||
|
|
|
|||
|
|
@ -2777,6 +2777,9 @@ the end of the file name.
|
|||
|
||||
If @var{text} is a string, @code{make-temp-file} inserts it in the file.
|
||||
|
||||
On Posix systems, Emacs creates the file with permissions that limit its
|
||||
access to the current user.
|
||||
|
||||
To prevent conflicts among different libraries running in the same
|
||||
Emacs, each Lisp program that uses @code{make-temp-file} should have its
|
||||
own @var{prefix}. The number added to the end of @var{prefix}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,20 @@ displayed on that terminal; the list of possible values is the same as
|
|||
for @code{framep} above.
|
||||
@end defun
|
||||
|
||||
@defun frame-initial-p &optional frame
|
||||
This predicate returns non-@code{nil} if @var{frame} is or holds the
|
||||
initial text frame that is used internally during daemon mode
|
||||
(@pxref{Initial Options, daemon,, emacs, The GNU Emacs Manual}), batch
|
||||
mode (@pxref{Batch Mode}), and the early stages of startup
|
||||
(@pxref{Startup Summary}). Interactive and graphical programs, for
|
||||
instance, can use this predicate to avoid operating on the initial
|
||||
frame, which is never displayed.
|
||||
|
||||
If @var{frame} is a terminal, this function returns non-@code{nil} if
|
||||
@var{frame} holds the initial frame. If @var{frame} is omitted or
|
||||
@code{nil}, it defaults to the selected one.
|
||||
@end defun
|
||||
|
||||
@cindex top-level frame
|
||||
On a graphical terminal we distinguish two types of frames: A normal
|
||||
@dfn{top-level frame} is a frame whose window-system window is a child
|
||||
|
|
@ -3029,7 +3043,7 @@ direction.
|
|||
See also @code{next-window} and @code{previous-window}, in @ref{Cyclic
|
||||
Window Ordering}.
|
||||
|
||||
Some Lisp programs need to find one or more frames that satisfy a
|
||||
Some Lisp programs need to find one or more frames that satisfy
|
||||
given criteria. The function @code{filtered-frame-list} is provided for
|
||||
this purpose.
|
||||
|
||||
|
|
|
|||
|
|
@ -828,14 +828,16 @@ if the user types the help character again.
|
|||
@cindex documentation groups
|
||||
@cindex groups of functions
|
||||
@cindex function groups
|
||||
@cindex shortdoc groups
|
||||
|
||||
Emacs can list functions based on various groupings. For instance,
|
||||
@code{string-trim} and @code{mapconcat} are ``string'' functions, so
|
||||
@kbd{M-x shortdoc RET string RET} will give an overview
|
||||
of functions that operate on strings.
|
||||
@kbd{M-x shortdoc RET string RET} will give an overview of these and
|
||||
other functions that operate on strings.
|
||||
|
||||
The documentation groups are created with the
|
||||
@code{define-short-documentation-group} macro.
|
||||
@code{define-short-documentation-group} macro. @xref{Documentation
|
||||
Group Tips}, for how to write good documentation groups.
|
||||
|
||||
@defmac define-short-documentation-group group &rest functions
|
||||
Define @var{group} as a group of functions, and provide short
|
||||
|
|
@ -846,6 +848,7 @@ summaries of using those functions. The optional argument
|
|||
(@var{func} [@var{keyword} @var{val}]@dots{})
|
||||
@end lisp
|
||||
|
||||
@cindex documentation group keywords
|
||||
The following keywords are recognized:
|
||||
|
||||
@table @code
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ in batch mode, e.g., with a command run by @kbd{@w{M-x compile
|
|||
* Compilation Tips:: Making compiled code run fast.
|
||||
* Warning Tips:: Turning off compiler warnings.
|
||||
* Documentation Tips:: Writing readable documentation strings.
|
||||
* Documentation Group Tips:: Writing useful documentation groups.
|
||||
* Comment Tips:: Conventions for writing comments.
|
||||
* Library Headers:: Standard headers for library packages.
|
||||
@end menu
|
||||
|
|
@ -934,6 +935,89 @@ If you do not anticipate anyone editing your code with older Emacs
|
|||
versions, there is no need for this work-around.
|
||||
@end itemize
|
||||
|
||||
@node Documentation Group Tips
|
||||
@section Tips for Documentation Groups
|
||||
@cindex documentation groups, tips
|
||||
@cindex tips for documentation groups
|
||||
|
||||
@cindex documentation groups, compatibility
|
||||
Documentation groups, available since Emacs 28, are useful to document
|
||||
functions of Lisp packages based on various groupings
|
||||
(@pxref{Documentation Groups}). This section gives some tips on how you
|
||||
can define documentation groups in your Lisp package in a way such that
|
||||
users of different Emacs versions can equally well use these groups.
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
To define documentation groups for your own Lisp package across
|
||||
different Emacs versions, you can use a boilerplate template along the
|
||||
lines of the following to make your package compile and load without
|
||||
errors:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
;;; well-doc.el --- a well-documented package -*- lexical-binding: t; -*-
|
||||
|
||||
@dots{} package header and contents @dots{}
|
||||
@end group
|
||||
|
||||
@group
|
||||
;; Explicitly require shortdoc for Emacs 28, which does not have an
|
||||
;; autoload for macro `define-short-documentation-group'. And for
|
||||
;; Emacs 30, so that we can redefine `shortdoc--check' later.
|
||||
(require 'shortdoc nil t)
|
||||
|
||||
(eval-when-compile
|
||||
|
||||
;; Default macro `define-short-documentation-group' for Emacs 27
|
||||
;; and older, which do not have the shortdoc feature at all.
|
||||
(unless (fboundp 'define-short-documentation-group)
|
||||
(defmacro define-short-documentation-group (&rest _)))
|
||||
|
||||
;; Disable too rigid shortdoc checks for Emacs 30, which let it
|
||||
;; error out on newer shortdoc keywords.
|
||||
(when (eq emacs-major-version 30)
|
||||
(fset 'shortdoc--check #'ignore)))
|
||||
@end group
|
||||
|
||||
@group
|
||||
(define-short-documentation-group well-doc
|
||||
@dots{})
|
||||
|
||||
;;; well-doc.el ends here
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@findex define-short-documentation-group
|
||||
If you do not intend to support some of the Emacs versions mentioned
|
||||
above, you can safely omit the corresponding forms from the template.
|
||||
If you intend to support only Emacs 31 and newer, you do not need any
|
||||
of the above and can just use @code{define-short-documentation-group}.
|
||||
|
||||
@item
|
||||
@cindex documentation group keywords, compatibility
|
||||
Newer Emacs versions might introduce newer documentation group features
|
||||
and keywords. However, these features or keywords will never break the
|
||||
display of a documentation group in older Emacs versions. Suppose you
|
||||
use a hypothetical group keyword @code{:super-pretty-print}, available
|
||||
in some future Emacs version, like this in your Lisp package
|
||||
@file{well-doc.el}:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
(define-short-documentation-group well-doc
|
||||
(well-doc-foo
|
||||
:eval (well-doc-foo)
|
||||
:super-pretty-print t))
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
That future Emacs version will then supposedly super-pretty-print the
|
||||
example for function @code{well-doc-foo}. Older Emacs versions will
|
||||
silently ignore keyword @code{:super-pretty-print} and show the example
|
||||
according to their regular display rules.
|
||||
@end itemize
|
||||
|
||||
@node Comment Tips
|
||||
@section Tips on Writing Comments
|
||||
@cindex comments, Lisp convention for
|
||||
|
|
|
|||
|
|
@ -6728,6 +6728,45 @@ See the docstring of variable @code{tramp-methods} for possible
|
|||
@code{foo-tramp-executable} in this example would be a Lisp constant,
|
||||
which is the program name of @command{foo}.
|
||||
|
||||
If a parameter doesn't have a static value but must be computed at
|
||||
runtime, a format specifier can be used, like @t{"%h"} in the example
|
||||
above. See the docstring of @code{tramp-methods}, which patterns are
|
||||
expanded in which parameter. Furthermore, other format specifiers can
|
||||
be added via the variable @code{tramp-extra-expand-args}.
|
||||
|
||||
The following parameters expand format specifiers for the
|
||||
@code{tramp-sh} backend: @code{tramp-copy-args},
|
||||
@code{tramp-copy-env}, @code{tramp-copy-file-name},
|
||||
@code{tramp-login-args}, @code{tramp-login-program},
|
||||
@code{tramp-remote-copy-args}.
|
||||
|
||||
The example above could use
|
||||
|
||||
@lisp
|
||||
(tramp-login-program "%1")
|
||||
@end lisp
|
||||
|
||||
And you could set @code{tramp-extra-expand-args} as connection-local value:
|
||||
|
||||
@lisp
|
||||
@group
|
||||
(defun foo-tramp-get-login-program (vec)
|
||||
"Return connection-local value of `tramp-login-program'."
|
||||
@dots{})
|
||||
@end group
|
||||
|
||||
@group
|
||||
(connection-local-set-profile-variables
|
||||
'foo-tramp-connection-local-default-profile
|
||||
'((tramp-extra-expand-args
|
||||
?1 (foo-tramp-get-login-program (car tramp-current-connection)))))
|
||||
|
||||
(connection-local-set-profiles
|
||||
'(:application tramp :protocol "foo")
|
||||
foo-tramp-connection-local-default-profile)
|
||||
@end group
|
||||
@end lisp
|
||||
|
||||
Another initialization could tell @value{tramp} which are the default
|
||||
user and host name for method @option{foo}. This is done by calling
|
||||
@code{tramp-set-completion-function}:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,16 @@ to look up issue github#1234, go to
|
|||
https://github.com/joaotavora/eglot/issues/1234.
|
||||
|
||||
|
||||
* Changes to upcoming Eglot
|
||||
* Changes in Eglot 1.23 (2/4/2026)
|
||||
|
||||
** Unbreak ELPA Eglot (github#1584)
|
||||
|
||||
Broken due to bad 'jsonrpc.el' dependency.
|
||||
|
||||
** 'eglot-report-progress' can be safely set to 'messages' (bug#80653)
|
||||
|
||||
|
||||
* Changes in Eglot 1.22 (1/4/2026)
|
||||
|
||||
** File watch limits to prevent resource exhaustion (github#1568)
|
||||
|
||||
|
|
@ -50,6 +59,19 @@ beneficial and helps servers avoid costly useless work.
|
|||
Eglot now sets 'imenu-create-index-function' using ':override' advice,
|
||||
making the integration cleaner and more predictable.
|
||||
|
||||
** Diagnostics from unopened files recalled on session start (github#1531)
|
||||
|
||||
Some servers (notably rust-analyzer) publish diagnostics for all
|
||||
project files at startup and never republish them on 'didOpen'. Eglot
|
||||
now saves such early diagnostics and reports them when those files are
|
||||
subsequently opened.
|
||||
|
||||
** Changes to 'eglot-server-programs'
|
||||
|
||||
- new 'static-ls' for 'haskell-mode'
|
||||
- new 'wat_server' for 'wat-mode' (WebAssembly Text) (bug#80188)
|
||||
- new 'elp' replaces 'erlang_ls' for 'erlang-mode' (bug#79943)
|
||||
|
||||
** Fixed textDocument/prepareRename support (github#1554)
|
||||
|
||||
Eglot now properly checks server capabilities before sending
|
||||
|
|
|
|||
46
etc/NEWS
46
etc/NEWS
|
|
@ -1760,6 +1760,15 @@ If 'page-delimiters' is set in 'whitespace-style', or the new minor mode
|
|||
width of the window. The new 'whitespace-page-delimiter' face can be
|
||||
used to customize the appearance.
|
||||
|
||||
---
|
||||
*** New user option 'whitespace-global-mode-buffers'.
|
||||
Normally, 'global-whitespace-mode' skips special buffers whose name
|
||||
starts with an asterisk '*'. This user option provides an override: it
|
||||
contains a list of regular expressions used to match the names of
|
||||
special buffers in which 'global-whitespace-mode' should turn on. The
|
||||
default value preserves the existing exception for the "*scratch*"
|
||||
buffer.
|
||||
|
||||
** Bookmark
|
||||
|
||||
---
|
||||
|
|
@ -2531,6 +2540,12 @@ of a literal newline. This prevents executing many Dired operations on
|
|||
such a file from failing and signaling an error. The default value of
|
||||
this user option is nil.
|
||||
|
||||
---
|
||||
*** New Dired handling of errors from 'ls'.
|
||||
When invoking a Dired command causes 'ls' to emit an error message,
|
||||
Emacs now displays the message in a popped up buffer instead of
|
||||
outputting it in the Dired buffer and signaling an error.
|
||||
|
||||
** Grep
|
||||
|
||||
+++
|
||||
|
|
@ -3187,6 +3202,11 @@ This minor mode binds 'xref-find-definitions-at-mouse' to
|
|||
definition, following the convention from other editors. The global
|
||||
minor mode 'global-xref-mouse-mode' will enable this in all buffers.
|
||||
|
||||
+++
|
||||
*** New command 'xref-change-to-xref-edit-mode'.
|
||||
It's bound to "e" and it switches an Xref buffer into an "editable" mode
|
||||
like similar features in Occur and Grep buffers.
|
||||
|
||||
** Revert
|
||||
|
||||
+++
|
||||
|
|
@ -4092,6 +4112,14 @@ to display its char argument on a given frame. This new function,
|
|||
unlike 'char-displayable-p', does not check whether the character can be
|
||||
encoded by the underlying terminal.
|
||||
|
||||
+++
|
||||
** New function 'frame-initial-p'.
|
||||
This predicate returns non-nil if a given frame or terminal is or holds,
|
||||
respectively, the initial text frame that is used internally during
|
||||
daemon mode, batch mode, and the early stages of startup. Interactive
|
||||
and graphical programs, for instance, can use this predicate to avoid
|
||||
operating on the initial frame, which is never displayed.
|
||||
|
||||
+++
|
||||
** New macros 'static-when' and 'static-unless'.
|
||||
Like 'static-if', these macros evaluate their condition at
|
||||
|
|
@ -4124,6 +4152,17 @@ change it globally with:
|
|||
---
|
||||
*** Loading a file displays a warning if there is no 'lexical-binding' cookie.
|
||||
|
||||
---
|
||||
** New function 'set-local'.
|
||||
This is the buffer local equivalent of the function 'set'.
|
||||
|
||||
+++
|
||||
** New macro 'setopt-local'.
|
||||
This is the buffer local version of 'setopt' for user options rather
|
||||
than plain variables and uses 'custom-set'/'set-local' to set variable
|
||||
values. A new argument, BUFFER-LOCAL, is passed to 'custom-set'
|
||||
functions to indicate the buffer local context.
|
||||
|
||||
+++
|
||||
** New macros 'incf' and 'decf'.
|
||||
They increment or decrement the value stored in a variable (a symbol),
|
||||
|
|
@ -4458,6 +4497,13 @@ singleton list.
|
|||
|
||||
* Changes in Emacs 31.1 on Non-Free Operating Systems
|
||||
|
||||
---
|
||||
** Support macOS Accessibility Zoom focus tracking.
|
||||
This is an important change for visually-impaired users. If macOS
|
||||
Accessibility Zoom is enabled (System Settings, Accessibility, Zoom)
|
||||
with keyboard focus tracking (Advanced...), Zoom is informed of updated
|
||||
cursor positions during each redisplay cycle.
|
||||
|
||||
---
|
||||
** Process execution has been optimized on Android.
|
||||
The run-time performance of subprocesses on recent Android releases,
|
||||
|
|
|
|||
|
|
@ -21,11 +21,20 @@
|
|||
|
||||
;;; Commentary
|
||||
|
||||
;; A theme that enables user options new users might be interested in.
|
||||
;; The guideline to enabling a feature is "would this interest someone
|
||||
;; who wouldn't even know that this option exists?". Please avoid
|
||||
;; opinionated cosmetic changes, that is the job of regular/color-scheme
|
||||
;; themes.
|
||||
;; This theme configures user options that we can reasonably expect the
|
||||
;; average, new user to want to enable, but would otherwise be unlikely
|
||||
;; to discover on their own. This includes support for convenience
|
||||
;; features, adjustment of default settings that are in place for
|
||||
;; historical reasons, aiding discoverability (at the potential cost of
|
||||
;; more visual noise) and trying and follow common conventions that
|
||||
;; other editors have established over the past decades.
|
||||
|
||||
;; The goal is to help providing a better starting point for users who
|
||||
;; would otherwise feel overwhelmed when first starting to use Emacs,
|
||||
;; without having to burden existing users with invasive changes to
|
||||
;; Emacs' default behavior. Options in the theme should NOT hinder
|
||||
;; developing a better understanding of Emacs (e.g. enabling emulation
|
||||
;; modes) or make opinionated cosmetic changes.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
|
@ -120,6 +129,7 @@ This minor mode will enable and disable the theme on startup."
|
|||
'(indent-tabs-mode nil)
|
||||
'(imenu-auto-rescan t)
|
||||
'(view-read-only t)
|
||||
'(column-number-mode t)
|
||||
|
||||
;;;; Directory managment-related options
|
||||
'(dired-auto-revert-buffer t)
|
||||
|
|
@ -153,7 +163,10 @@ This minor mode will enable and disable the theme on startup."
|
|||
;;;; Frame- and window-related options
|
||||
'(frame-inhibit-implied-resize t)
|
||||
'(tab-bar-history-mode t)
|
||||
'(tab-bar-show 0))
|
||||
'(tab-bar-show 0)
|
||||
|
||||
;;;; Programming-related options
|
||||
'(compilation-scroll-output 'first-error))
|
||||
|
||||
(provide-theme 'newcomers-presets)
|
||||
;;; newcomers-presets-theme.el ends here
|
||||
|
|
|
|||
|
|
@ -316,6 +316,11 @@ main (int argc, char **argv)
|
|||
SCMP_A0_32 (SCMP_CMP_EQ, 0) /* pid == 0 (current process) */,
|
||||
SCMP_A2_64 (SCMP_CMP_EQ, 0) /* new_limit == NULL */);
|
||||
|
||||
/* Allow reading the scheduler policy and affinity, so num_processors
|
||||
can determine the number of usable CPUs. */
|
||||
RULE0 (SCMP_ACT_ALLOW, SCMP_SYS (sched_getaffinity));
|
||||
RULE0 (SCMP_ACT_ALLOW, SCMP_SYS (sched_getscheduler));
|
||||
|
||||
/* Block changing resource limits, but don't crash. */
|
||||
RULE (SCMP_ACT_ERRNO (EPERM), SCMP_SYS (prlimit64),
|
||||
SCMP_A0_32 (SCMP_CMP_EQ, 0) /* pid == 0 (current process) */,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ HOST, USER, PORT, REQUIRE, and MAX."
|
|||
((null host)
|
||||
;; Do not build a result, as none will match when HOST is nil
|
||||
nil)
|
||||
((not (file-directory-p auth-source-pass-filename))
|
||||
;; Do nothing if the password-store folder doesn't exist.
|
||||
nil)
|
||||
(auth-source-pass-extra-query-keywords
|
||||
(auth-source-pass--build-result-many host port user require max))
|
||||
(t
|
||||
|
|
|
|||
|
|
@ -1084,7 +1084,7 @@ even if it doesn't match the type.)
|
|||
\(fn [VARIABLE VALUE]...)"
|
||||
(declare (debug setq))
|
||||
(unless (evenp (length pairs))
|
||||
(error "PAIRS must have an even number of variable/value members"))
|
||||
(signal 'wrong-number-of-arguments (list 'setopt (length pairs))))
|
||||
(let ((expr nil))
|
||||
(while pairs
|
||||
(unless (symbolp (car pairs))
|
||||
|
|
@ -1100,11 +1100,53 @@ even if it doesn't match the type.)
|
|||
;; Check that the type is correct.
|
||||
(when-let* ((type (get variable 'custom-type)))
|
||||
(unless (widget-apply (widget-convert type) :match value)
|
||||
(warn "Value `%S' for variable `%s' does not match its type \"%s\""
|
||||
value variable type)))
|
||||
(warn "Value does not match %S's type `%S': %S" variable type value)))
|
||||
(put variable 'custom-check-value (list value))
|
||||
(funcall (or (get variable 'custom-set) #'set-default) variable value))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro setopt-local (&rest pairs)
|
||||
"Set buffer local VARIABLE/VALUE pairs, and return the final VALUE.
|
||||
This is like `setq-local', but is meant for user options instead of
|
||||
plain variables. This means that `setopt-local' will execute any
|
||||
`custom-set' form associated with VARIABLE. Unlike `setopt',
|
||||
`setopt-local' does not affect a user option's global value.
|
||||
|
||||
Note that `setopt-local' will emit a warning if the type of a VALUE does
|
||||
not match the type of the corresponding VARIABLE as declared by
|
||||
`defcustom'. (VARIABLE will be assigned the value even if it doesn't
|
||||
match the type.)
|
||||
|
||||
Signal an error if a `custom-set' form does not support the
|
||||
`buffer-local' argument.
|
||||
|
||||
\(fn [VARIABLE VALUE]...)"
|
||||
(declare (debug setq))
|
||||
(unless (evenp (length pairs))
|
||||
(signal 'wrong-number-of-arguments (list 'setopt-local (length pairs))))
|
||||
(let ((expr nil))
|
||||
(while pairs
|
||||
(unless (symbolp (car pairs))
|
||||
(error "Attempting to set a non-symbol: %s" (car pairs)))
|
||||
(push `(setopt--set-local ',(car pairs) ,(cadr pairs))
|
||||
expr)
|
||||
(setq pairs (cddr pairs)))
|
||||
(macroexp-progn (nreverse expr))))
|
||||
|
||||
;;;###autoload
|
||||
(defun setopt--set-local (variable value)
|
||||
(custom-load-symbol variable)
|
||||
;; Check that the type is correct.
|
||||
(when-let* ((type (get variable 'custom-type)))
|
||||
(unless (widget-apply (widget-convert type) :match value)
|
||||
(warn "Value does not match %S's type `%S': %S" variable type value)))
|
||||
(condition-case _
|
||||
(funcall (or (get variable 'custom-set)
|
||||
(lambda (x v &optional _) (set-local x v)))
|
||||
variable value 'buffer-local)
|
||||
(wrong-number-of-arguments
|
||||
(error "The setter of %S does not support setopt-local" variable))))
|
||||
|
||||
;;;###autoload
|
||||
(defun customize-save-variable (variable value &optional comment)
|
||||
"Set the default for VARIABLE to VALUE, and save it for future sessions.
|
||||
|
|
|
|||
|
|
@ -398,7 +398,11 @@ then it searches *all* buffers."
|
|||
;; Set it so `dabbrev-capf' won't reset the vars.
|
||||
(setq dabbrev--last-abbrev-location (point-marker))
|
||||
(let ((completion-at-point-functions '(dabbrev-capf)))
|
||||
(completion-at-point)))
|
||||
(unless (completion-at-point)
|
||||
(user-error "No dynamic expansion for \"%s\" found%s"
|
||||
(dabbrev--abbrev-at-point)
|
||||
(if dabbrev--check-other-buffers
|
||||
"" " in this-buffer")))))
|
||||
|
||||
(defun dabbrev-capf ()
|
||||
"Dabbrev completion function for `completion-at-point-functions'."
|
||||
|
|
|
|||
|
|
@ -775,6 +775,7 @@ if different)."
|
|||
;; Don't delete daemon's initial frame, or
|
||||
;; we'll never be able to close the last
|
||||
;; client's frame (Bug#26912).
|
||||
;; Use `frame-initial-p'?
|
||||
(and (daemonp) (eq frame terminal-frame))
|
||||
(frame-parameter frame 'desktop-dont-clear))
|
||||
(delete-frame frame))
|
||||
|
|
@ -1067,9 +1068,8 @@ DIRNAME must be the directory in which the desktop file will be saved."
|
|||
(and (not (frame-parameter frame 'desktop-dont-save))
|
||||
;; Don't save daemon initial frames, since we cannot (and don't
|
||||
;; need to) restore them.
|
||||
(not (and (daemonp)
|
||||
(equal (terminal-name (frame-terminal frame))
|
||||
"initial_terminal")))))
|
||||
(not (and (daemonp) ;; FIXME: Remove `daemonp'?
|
||||
(frame-initial-p frame)))))
|
||||
|
||||
(defconst desktop--app-id `(desktop . ,desktop-file-version))
|
||||
|
||||
|
|
@ -1260,7 +1260,7 @@ This function also sets `desktop-dirname' to nil."
|
|||
"True if calling `desktop-restore-frameset' will actually restore it."
|
||||
(and desktop-restore-frames desktop-saved-frameset
|
||||
;; Don't restore frames when the selected frame is the daemon's
|
||||
;; initial frame.
|
||||
;; initial frame. Use `frame-initial-p'?
|
||||
(not (and (daemonp) (eq (selected-frame) terminal-frame)))
|
||||
t))
|
||||
|
||||
|
|
|
|||
|
|
@ -649,6 +649,10 @@ The match starts at the beginning of the line and ends after the end
|
|||
of the line.
|
||||
Subexpression 2 must end right before the \\n.")
|
||||
|
||||
(defvar dired--ls-error-buffer nil
|
||||
"Non-nil if the current dired invocation yields an `ls' error.
|
||||
The non-nil value is the buffer containing the error message.")
|
||||
|
||||
|
||||
;;; Faces
|
||||
|
||||
|
|
@ -1230,7 +1234,16 @@ Type \\[describe-mode] after entering Dired for more info.
|
|||
If DIRNAME is already in a Dired buffer, that buffer is used without refresh."
|
||||
;; Cannot use (interactive "D") because of wildcards.
|
||||
(interactive (dired-read-dir-and-switches ""))
|
||||
(pop-to-buffer-same-window (dired-noselect dirname switches)))
|
||||
(prog1 (pop-to-buffer-same-window (dired-noselect dirname switches))
|
||||
(dired--display-ls-error)))
|
||||
|
||||
;; This is needed to let clicks on the menu bar invoke Dired even if
|
||||
;; some feature remaps the Dired command to another command.
|
||||
;;;###autoload
|
||||
(defun dired-from-menubar (dirname &optional switches)
|
||||
"Edit an existing directory."
|
||||
(interactive (dired-read-dir-and-switches ""))
|
||||
(dired dirname switches))
|
||||
|
||||
;;;###autoload (keymap-set ctl-x-4-map "d" #'dired-other-window)
|
||||
;;;###autoload
|
||||
|
|
@ -1240,21 +1253,24 @@ If this command needs to split the current window, it by default obeys
|
|||
the user options `split-height-threshold' and `split-width-threshold',
|
||||
when it decides whether to split the window horizontally or vertically."
|
||||
(interactive (dired-read-dir-and-switches "in other window "))
|
||||
(switch-to-buffer-other-window (dired-noselect dirname switches)))
|
||||
(prog1 (switch-to-buffer-other-window (dired-noselect dirname switches))
|
||||
(dired--display-ls-error)))
|
||||
|
||||
;;;###autoload (keymap-set ctl-x-5-map "d" #'dired-other-frame)
|
||||
;;;###autoload
|
||||
(defun dired-other-frame (dirname &optional switches)
|
||||
"\"Edit\" directory DIRNAME. Like `dired' but make a new frame."
|
||||
(interactive (dired-read-dir-and-switches "in other frame "))
|
||||
(switch-to-buffer-other-frame (dired-noselect dirname switches)))
|
||||
(prog1 (switch-to-buffer-other-frame (dired-noselect dirname switches))
|
||||
(dired--display-ls-error)))
|
||||
|
||||
;;;###autoload (keymap-set tab-prefix-map "d" #'dired-other-tab)
|
||||
;;;###autoload
|
||||
(defun dired-other-tab (dirname &optional switches)
|
||||
"\"Edit\" directory DIRNAME. Like `dired' but make a new tab."
|
||||
(interactive (dired-read-dir-and-switches "in other tab "))
|
||||
(switch-to-buffer-other-tab (dired-noselect dirname switches)))
|
||||
(prog1 (switch-to-buffer-other-tab (dired-noselect dirname switches))
|
||||
(dired--display-ls-error)))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-noselect (dir-or-list &optional switches)
|
||||
|
|
@ -1439,10 +1455,19 @@ The return value is the target column for the file names."
|
|||
(let ((failed t))
|
||||
(unwind-protect
|
||||
(progn (dired-readin)
|
||||
(setq failed nil))
|
||||
;; dired-readin can fail if parent directories are inaccessible.
|
||||
;; Don't leave an empty buffer around in that case.
|
||||
(if failed (kill-buffer buffer))))
|
||||
;; Check for file entries (they are listed below the
|
||||
;; directory name and (if present) wildcard lines).
|
||||
(while (and (skip-syntax-forward "\s")
|
||||
(looking-at "\\(.+:$\\|wildcard\\)"))
|
||||
(forward-line))
|
||||
(unless (eobp)
|
||||
(setq failed nil)))
|
||||
;; No file entries indicates an `ls' error, and `dired-readin'
|
||||
;; can fail if parent directories are inaccessible. In either
|
||||
;; case don't leave the Dired buffer around.
|
||||
(when failed
|
||||
(kill-buffer buffer)
|
||||
(setq buffer nil))))
|
||||
(goto-char (point-min))
|
||||
(dired-initial-position dirname))
|
||||
(when (consp dired-directory)
|
||||
|
|
@ -4003,20 +4028,11 @@ Considers buffers closer to the car of `buffer-list' to be more recent."
|
|||
(not (memq buffer1 (memq buffer2 (buffer-list))))))
|
||||
|
||||
(defun dired--filename-with-newline-p ()
|
||||
"Check if a file name in this directory has a newline.
|
||||
Return non-nil if at least one file name in this directory contains
|
||||
either a literal newline or the string \"\\n\")."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(catch 'found
|
||||
(while (not (eobp))
|
||||
(when (dired-move-to-filename)
|
||||
(let ((fn (buffer-substring-no-properties
|
||||
(point) (dired-move-to-end-of-filename))))
|
||||
(when (or (memq 10 (seq-into fn 'list))
|
||||
(string-search "\\n" fn))
|
||||
(throw 'found t))))
|
||||
(forward-line)))))
|
||||
"Check whether a file name in this directory has a newline.
|
||||
Return non-nil if at least one file name in this directory contains a
|
||||
newline character (regardless of whether Dired displays the character as
|
||||
a literal newline or as \"\\n\")."
|
||||
(directory-files default-directory nil "\n"))
|
||||
|
||||
(defun dired--remove-b-switch ()
|
||||
"Remove all variants of the `b' switch from `dired-actual-switches'.
|
||||
|
|
@ -4094,6 +4110,13 @@ See `%s' for other alternatives and more information."))
|
|||
(set-window-point (get-buffer-window)
|
||||
(search-backward "Warning (dired)")))))
|
||||
|
||||
(defun dired--display-ls-error ()
|
||||
"Pop up a buffer displaying the current `ls' error, if any."
|
||||
(when dired--ls-error-buffer
|
||||
(let* ((errwin (display-buffer dired--ls-error-buffer)))
|
||||
(fit-window-to-buffer errwin))
|
||||
(setq dired--ls-error-buffer nil)))
|
||||
|
||||
|
||||
;;; Deleting files
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ See Info node `Displaying Boundaries' for details."
|
|||
(defun display-fill-column-indicator--turn-on ()
|
||||
"Turn on `display-fill-column-indicator-mode'."
|
||||
(unless (or (minibufferp)
|
||||
;; Use `frame-initial-p'?
|
||||
(and (daemonp) (eq (selected-frame) terminal-frame)))
|
||||
(display-fill-column-indicator-mode)))
|
||||
|
||||
|
|
|
|||
|
|
@ -1901,6 +1901,8 @@ See Info node `(elisp) Integer Basics'."
|
|||
sqlite-available-p sqlitep
|
||||
;; syntax.c
|
||||
standard-syntax-table syntax-table syntax-table-p
|
||||
;; terminal.c
|
||||
frame-initial-p
|
||||
;; thread.c
|
||||
current-thread
|
||||
;; timefns.c
|
||||
|
|
|
|||
|
|
@ -195,8 +195,7 @@ the debugger will not be entered."
|
|||
;; backtrace to stdout. This happens for example while
|
||||
;; handling an error in code from early-init.el with
|
||||
;; --debug-init.
|
||||
(and (eq t (framep (selected-frame)))
|
||||
(equal "initial_terminal" (terminal-name)))))
|
||||
(frame-initial-p)))
|
||||
;; Don't let `inhibit-message' get in our way (especially important if
|
||||
;; `non-interactive-frame' evaluated to a non-nil value.
|
||||
(inhibit-message nil)
|
||||
|
|
|
|||
1528
lisp/emacs-lisp/shortdoc-doc.el
Normal file
1528
lisp/emacs-lisp/shortdoc-doc.el
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -372,6 +372,7 @@ entirely by setting `warning-suppress-types' or
|
|||
(if (bolp)
|
||||
(forward-char -1))
|
||||
(message "%s" (buffer-substring start (point))))))
|
||||
;; Use `frame-initial-p'?
|
||||
((and (daemonp) (eq (selected-frame) terminal-frame))
|
||||
;; Display daemon startup warnings on the first client frame.
|
||||
(letrec ((afterfun
|
||||
|
|
|
|||
|
|
@ -232,7 +232,22 @@ encryption is used."
|
|||
(epa-file-decode-and-insert
|
||||
string file visit beg end replace))))
|
||||
(if visit
|
||||
(set-visited-file-modtime))))
|
||||
(set-visited-file-modtime)))
|
||||
;; The decoded file could still need another massage from a
|
||||
;; file name handler, for example a file like
|
||||
;; "folder.sym.tar.gz.gpg". (Bug#80641)
|
||||
(when (find-file-name-handler
|
||||
(file-name-sans-extension file)
|
||||
'insert-file-contents)
|
||||
(let ((tmpfile
|
||||
(make-temp-file
|
||||
nil nil
|
||||
(file-name-extension (file-name-base file) 'period))))
|
||||
(let (file-name-handler-alist) (write-region nil nil tmpfile))
|
||||
(erase-buffer)
|
||||
(insert-file-contents tmpfile)
|
||||
(setq length (- (point-max) (point-min)))
|
||||
(delete-file tmpfile))))
|
||||
(if (and local-copy
|
||||
(file-exists-p local-copy))
|
||||
(delete-file local-copy)))
|
||||
|
|
|
|||
|
|
@ -1006,7 +1006,7 @@ Failing that, choose the first face in both NEW-FACES and NORMALS."
|
|||
(dolist (candidate (cdr ranks))
|
||||
(when (and (not (equal candidate choice))
|
||||
(gethash candidate (car new-faces))
|
||||
(gethash choice normals))
|
||||
(gethash candidate normals))
|
||||
(throw 'face candidate)))
|
||||
;; Otherwise, go with any "normal" face other than
|
||||
;; `choice' in the region.
|
||||
|
|
|
|||
|
|
@ -1693,11 +1693,18 @@ time `erc-mode-hook' runs for any connection."
|
|||
(declare (indent 1))
|
||||
(cl-assert (stringp (car args)))
|
||||
(if (derived-mode-p 'erc-mode)
|
||||
(unless (or (erc-with-server-buffer ; needs `erc-server-process'
|
||||
(apply #'erc-button--display-error-notice-with-keys
|
||||
(current-buffer) args)
|
||||
t)
|
||||
erc--target) ; unlikely
|
||||
(unless
|
||||
(or (erc-with-server-buffer ; needs `erc-server-process'
|
||||
(let ((fn
|
||||
(lambda (buffer)
|
||||
(erc-with-buffer (buffer)
|
||||
(apply #'erc-button--display-error-notice-with-keys
|
||||
buffer args)))))
|
||||
(if erc--msg-props
|
||||
(run-at-time nil nil fn (current-buffer))
|
||||
(funcall fn (current-buffer))))
|
||||
t)
|
||||
erc--target) ; unlikely
|
||||
(let (hook)
|
||||
(setq hook
|
||||
(lambda (_)
|
||||
|
|
|
|||
277
lisp/files.el
277
lisp/files.el
|
|
@ -1790,7 +1790,10 @@ If DIR-FLAG is non-nil, create a new empty directory instead of a file.
|
|||
If SUFFIX is non-nil, add that at the end of the file name.
|
||||
|
||||
If TEXT is a string, insert it into the new file; DIR-FLAG should be nil.
|
||||
Otherwise the file will be empty."
|
||||
Otherwise the file will be empty.
|
||||
|
||||
On Posix systems, the file/directory is created with access mode bits
|
||||
that limit access to the current user."
|
||||
(let ((absolute-prefix
|
||||
(if (or (zerop (length prefix)) (member prefix '("." "..")))
|
||||
(concat (file-name-as-directory temporary-file-directory) prefix)
|
||||
|
|
@ -8320,41 +8323,24 @@ Valid wildcards are `*', `?', `[abc]' and `[a-z]'."
|
|||
(forward-line -1))
|
||||
(if (let ((case-fold-search nil)) (looking-at "//DIRED//"))
|
||||
(let ((end (line-end-position))
|
||||
(linebeg (point))
|
||||
error-lines)
|
||||
;; Find all the lines that are error messages,
|
||||
;; and record the bounds of each one.
|
||||
(goto-char beg)
|
||||
(while (< (point) linebeg)
|
||||
(or (eql (following-char) ?\s)
|
||||
(push (list (point) (line-end-position)) error-lines))
|
||||
(forward-line 1))
|
||||
(setq error-lines (nreverse error-lines))
|
||||
;; Now read the numeric positions of file names.
|
||||
(linebeg (point)))
|
||||
;; Read the numeric positions of file names.
|
||||
(goto-char linebeg)
|
||||
(forward-word-strictly 1)
|
||||
(forward-char 3)
|
||||
(while (< (point) end)
|
||||
(let ((start (insert-directory-adj-pos
|
||||
(+ beg (read (current-buffer)))
|
||||
error-lines))
|
||||
(end (insert-directory-adj-pos
|
||||
(+ beg (read (current-buffer)))
|
||||
error-lines)))
|
||||
(if (memq (char-after end) '(?\n ?\s ?/ ?* ?@ ?% ?= ?|))
|
||||
;; End is followed by \n or by output of -F.
|
||||
(put-text-property start end 'dired-filename t)
|
||||
;; It seems that we can't trust ls's output as to
|
||||
;; byte positions of filenames.
|
||||
(put-text-property beg (point) 'dired-filename nil)
|
||||
(end-of-line))))
|
||||
(let ((start (+ beg (read (current-buffer))))
|
||||
(end (+ beg (read (current-buffer)))))
|
||||
(when (memq (char-after end) '(?\n ?\s ?/ ?* ?@ ?% ?= ?|))
|
||||
;; End is followed by \n or by output of -F.
|
||||
(put-text-property start end 'dired-filename t))))
|
||||
(goto-char end)
|
||||
(beginning-of-line)
|
||||
(delete-region (point) (progn (forward-line 1) (point))))
|
||||
;; Take care of the case where the ls output contains a
|
||||
;; "//DIRED-OPTIONS//"-line, but no "//DIRED//"-line
|
||||
;; and we went one line too far back (see above).
|
||||
(forward-line 1))
|
||||
(unless (bobp) (forward-line 1)))
|
||||
(if (let ((case-fold-search nil)) (looking-at "//DIRED-OPTIONS//"))
|
||||
(delete-region (point) (progn (forward-line 1) (point))))))
|
||||
|
||||
|
|
@ -8363,12 +8349,12 @@ Valid wildcards are `*', `?', `[abc]' and `[a-z]'."
|
|||
;; FULL-DIRECTORY-P is nil.
|
||||
;; The single line of output must display FILE's name as it was
|
||||
;; given, namely, an absolute path name.
|
||||
;; - must insert exactly one line for each file if WILDCARD or
|
||||
;; - must insert exactly one entry for each file if WILDCARD or
|
||||
;; FULL-DIRECTORY-P is t, plus one optional "total" line
|
||||
;; before the file lines, plus optional text after the file lines.
|
||||
;; Lines are delimited by "\n", so filenames containing "\n" are not
|
||||
;; allowed.
|
||||
;; File lines should display the basename.
|
||||
;; Entries are delimited by "\n", but file names containing "\n" are
|
||||
;; allowed and by default the "\n" is displayed as a literal newline.
|
||||
;; File entries should display the basename.
|
||||
;; - must be consistent with
|
||||
;; - functions dired-move-to-filename, (these two define what a file line is)
|
||||
;; dired-move-to-end-of-filename,
|
||||
|
|
@ -8410,10 +8396,10 @@ normally equivalent short `-D' option is just passed on to
|
|||
(declare-function ls-lisp--insert-directory "ls-lisp")
|
||||
(ls-lisp--insert-directory file switches wildcard full-directory-p))
|
||||
(t
|
||||
(let (result (beg (point)))
|
||||
(let ((beg (point))
|
||||
(errfile (make-temp-file "lserr")))
|
||||
|
||||
;; Read the actual directory using `insert-directory-program'.
|
||||
;; RESULT gets the status code.
|
||||
(let* (;; We at first read by no-conversion, then after
|
||||
;; putting text property `dired-filename, decode one
|
||||
;; bunch by one to preserve that property.
|
||||
|
|
@ -8423,143 +8409,88 @@ normally equivalent short `-D' option is just passed on to
|
|||
(and enable-multibyte-characters
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system))))
|
||||
(setq result
|
||||
(if wildcard
|
||||
;; If the wildcard is just in the file part, then run ls in
|
||||
;; the directory part of the file pattern using the last
|
||||
;; component as argument. Otherwise, run ls in the longest
|
||||
;; subdirectory of the directory part free of wildcards; use
|
||||
;; the remaining of the file pattern as argument.
|
||||
(let* ((dir-wildcard (insert-directory-wildcard-in-dir-p file))
|
||||
(default-directory
|
||||
(cond (dir-wildcard (car dir-wildcard))
|
||||
(t
|
||||
(if (file-name-absolute-p file)
|
||||
(file-name-directory file)
|
||||
(file-name-directory (expand-file-name file))))))
|
||||
(pattern (if dir-wildcard (cdr dir-wildcard) (file-name-nondirectory file))))
|
||||
;; NB since switches is passed to the shell, be
|
||||
;; careful of malicious values, eg "-l;reboot".
|
||||
;; See eg dired-safe-switches-p.
|
||||
(call-process
|
||||
shell-file-name nil t nil
|
||||
shell-command-switch
|
||||
(concat (if (memq system-type '(ms-dos windows-nt))
|
||||
""
|
||||
"\\") ; Disregard Unix shell aliases!
|
||||
insert-directory-program
|
||||
" -d "
|
||||
;; Quote switches that require quoting
|
||||
;; such as "--block-size='1". But don't
|
||||
;; quote switches that use patterns
|
||||
;; such as "--ignore=PATTERN" (bug#71935).
|
||||
(mapconcat #'shell-quote-wildcard-pattern
|
||||
(if (stringp switches)
|
||||
(split-string-and-unquote switches)
|
||||
switches)
|
||||
" ")
|
||||
" -- "
|
||||
;; Quote some characters that have
|
||||
;; special meanings in shells; but
|
||||
;; don't quote the wildcards--we want
|
||||
;; them to be special. We also
|
||||
;; currently don't quote the quoting
|
||||
;; characters in case people want to
|
||||
;; use them explicitly to quote
|
||||
;; wildcard characters.
|
||||
(shell-quote-wildcard-pattern pattern))))
|
||||
;; SunOS 4.1.3, SVr4 and others need the "." to list the
|
||||
;; directory if FILE is a symbolic link.
|
||||
(unless full-directory-p
|
||||
(setq switches
|
||||
(cond
|
||||
((stringp switches) (concat switches " -d"))
|
||||
((member "-d" switches) switches)
|
||||
(t (append switches '("-d"))))))
|
||||
(if (string-match "\\`~" file)
|
||||
(setq file (expand-file-name file)))
|
||||
(apply #'call-process
|
||||
insert-directory-program nil t nil
|
||||
(append
|
||||
(if (listp switches) switches
|
||||
(unless (equal switches "")
|
||||
;; Split the switches at any spaces so we can
|
||||
;; pass separate options as separate args.
|
||||
(split-string-and-unquote switches)))
|
||||
;; Avoid lossage if FILE starts with `-'.
|
||||
'("--")
|
||||
(list file))))))
|
||||
(if wildcard
|
||||
;; If the wildcard is just in the file part, then run ls in
|
||||
;; the directory part of the file pattern using the last
|
||||
;; component as argument. Otherwise, run ls in the longest
|
||||
;; subdirectory of the directory part free of wildcards; use
|
||||
;; the remaining of the file pattern as argument.
|
||||
(let* ((dir-wildcard
|
||||
(insert-directory-wildcard-in-dir-p file))
|
||||
(default-directory
|
||||
(cond (dir-wildcard (car dir-wildcard))
|
||||
(t
|
||||
(if (file-name-absolute-p file)
|
||||
(file-name-directory file)
|
||||
(file-name-directory
|
||||
(expand-file-name file))))))
|
||||
(pattern (if dir-wildcard
|
||||
(cdr dir-wildcard)
|
||||
(file-name-nondirectory file))))
|
||||
;; NB since switches is passed to the shell, be
|
||||
;; careful of malicious values, eg "-l;reboot".
|
||||
;; See eg dired-safe-switches-p.
|
||||
(call-process
|
||||
shell-file-name nil (list t errfile) nil
|
||||
shell-command-switch
|
||||
(concat (if (memq system-type '(ms-dos windows-nt))
|
||||
""
|
||||
"\\") ; Disregard Unix shell aliases!
|
||||
insert-directory-program
|
||||
" -d "
|
||||
;; Quote switches that require quoting
|
||||
;; such as "--block-size='1". But don't
|
||||
;; quote switches that use patterns
|
||||
;; such as "--ignore=PATTERN" (bug#71935).
|
||||
(mapconcat #'shell-quote-wildcard-pattern
|
||||
(if (stringp switches)
|
||||
(split-string-and-unquote switches)
|
||||
switches)
|
||||
" ")
|
||||
" -- "
|
||||
;; Quote some characters that have
|
||||
;; special meanings in shells; but
|
||||
;; don't quote the wildcards--we want
|
||||
;; them to be special. We also
|
||||
;; currently don't quote the quoting
|
||||
;; characters in case people want to
|
||||
;; use them explicitly to quote
|
||||
;; wildcard characters.
|
||||
(shell-quote-wildcard-pattern pattern))))
|
||||
;; SunOS 4.1.3, SVr4 and others need the "." to list the
|
||||
;; directory if FILE is a symbolic link.
|
||||
(unless full-directory-p
|
||||
(setq switches
|
||||
(cond
|
||||
((stringp switches) (concat switches " -d"))
|
||||
((member "-d" switches) switches)
|
||||
(t (append switches '("-d"))))))
|
||||
(if (string-match "\\`~" file)
|
||||
(setq file (expand-file-name file)))
|
||||
(apply #'call-process
|
||||
insert-directory-program nil (list t errfile) nil
|
||||
(append
|
||||
(if (listp switches) switches
|
||||
(unless (equal switches "")
|
||||
;; Split the switches at any spaces so we can
|
||||
;; pass separate options as separate args.
|
||||
(split-string-and-unquote switches)))
|
||||
;; Avoid lossage if FILE starts with `-'.
|
||||
'("--")
|
||||
(list file)))))
|
||||
|
||||
;; If we got "//DIRED//" in the output, it means we got a real
|
||||
;; directory listing, even if `ls' returned nonzero.
|
||||
;; So ignore any errors.
|
||||
(when (if (stringp switches)
|
||||
(string-match "--dired\\>" switches)
|
||||
(member "--dired" switches))
|
||||
(save-excursion
|
||||
(let ((case-fold-search nil))
|
||||
(forward-line -2)
|
||||
(when (looking-at "//SUBDIRED//")
|
||||
(forward-line -1))
|
||||
(if (looking-at "//DIRED//")
|
||||
(setq result 0)))))
|
||||
;; If `ls' emits an error message, copy it to a buffer that will
|
||||
;; be displayed when a Dired invocation results in the `ls'
|
||||
;; error.
|
||||
(when (> (file-attribute-size (file-attributes errfile)) 0)
|
||||
(defvar dired--ls-error-buffer) ; Pacify byte-compiler.
|
||||
(let ((errbuf (get-buffer-create "*ls error*")))
|
||||
(with-current-buffer errbuf
|
||||
(erase-buffer)
|
||||
(insert-file-contents errfile))
|
||||
(setq dired--ls-error-buffer errbuf)))
|
||||
(delete-file errfile)
|
||||
|
||||
(when (and (not (eq 0 result))
|
||||
(eq insert-directory-ls-version 'unknown))
|
||||
;; The first time ls returns an error,
|
||||
;; find the version numbers of ls,
|
||||
;; and set insert-directory-ls-version
|
||||
;; to > if it is more than 5.2.1, < if it is less, nil if it
|
||||
;; is equal or if the info cannot be obtained.
|
||||
;; (That can mean it isn't GNU ls.)
|
||||
(let ((version-out
|
||||
(with-temp-buffer
|
||||
(call-process "ls" nil t nil "--version")
|
||||
(buffer-string))))
|
||||
(setq insert-directory-ls-version
|
||||
(if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
|
||||
(let* ((version (match-string 1 version-out))
|
||||
(split (split-string version "[.]"))
|
||||
(numbers (mapcar #'string-to-number split))
|
||||
(min '(5 2 1))
|
||||
comparison)
|
||||
(while (and (not comparison) (or numbers min))
|
||||
(cond ((null min)
|
||||
(setq comparison #'>))
|
||||
((null numbers)
|
||||
(setq comparison #'<))
|
||||
((> (car numbers) (car min))
|
||||
(setq comparison #'>))
|
||||
((< (car numbers) (car min))
|
||||
(setq comparison #'<))
|
||||
(t
|
||||
(setq numbers (cdr numbers)
|
||||
min (cdr min)))))
|
||||
(or comparison #'=))
|
||||
nil))))
|
||||
|
||||
;; For GNU ls versions 5.2.2 and up, ignore minor errors.
|
||||
(when (and (eq 1 result) (eq insert-directory-ls-version #'>))
|
||||
(setq result 0))
|
||||
|
||||
;; If `insert-directory-program' failed, signal an error.
|
||||
(unless (eq 0 result)
|
||||
;; Delete the error message it may have output.
|
||||
(delete-region beg (point))
|
||||
;; On non-Posix systems, we cannot open a directory, so
|
||||
;; don't even try, because that will always result in
|
||||
;; the ubiquitous "Access denied". Instead, show the
|
||||
;; command line so the user can try to guess what went wrong.
|
||||
(if (and (file-directory-p file)
|
||||
(memq system-type '(ms-dos windows-nt)))
|
||||
(error
|
||||
"Reading directory: \"%s %s -- %s\" exited with status %s"
|
||||
insert-directory-program
|
||||
(if (listp switches) (concat switches) switches)
|
||||
file result)
|
||||
;; Unix. Access the file to get a suitable error.
|
||||
(access-file file "Reading directory")
|
||||
(error "Listing directory failed but `access-file' worked")))
|
||||
(insert-directory-clean beg switches)
|
||||
;; Now decode what read if necessary.
|
||||
(let ((coding (or coding-system-for-read
|
||||
|
|
@ -8594,18 +8525,6 @@ normally equivalent short `-D' option is just passed on to
|
|||
(put-text-property pos (point)
|
||||
'dired-filename t))))))))))))
|
||||
|
||||
(defun insert-directory-adj-pos (pos error-lines)
|
||||
"Convert `ls --dired' file name position value POS to a buffer position.
|
||||
File name position values returned in ls --dired output
|
||||
count only stdout; they don't count the error messages sent to stderr.
|
||||
So this function converts to them to real buffer positions.
|
||||
ERROR-LINES is a list of buffer positions of error message lines,
|
||||
of the form (START END)."
|
||||
(while (and error-lines (< (caar error-lines) pos))
|
||||
(setq pos (+ pos (- (nth 1 (car error-lines)) (nth 0 (car error-lines)))))
|
||||
(pop error-lines))
|
||||
pos)
|
||||
|
||||
(defun insert-directory-safely (file switches
|
||||
&optional wildcard full-directory-p)
|
||||
"Insert directory listing for FILE, formatted according to SWITCHES.
|
||||
|
|
|
|||
|
|
@ -493,6 +493,7 @@ there (in decreasing order of priority)."
|
|||
(setq parms (append initial-frame-alist window-system-frame-alist
|
||||
default-frame-alist parms nil))
|
||||
;; Don't enable tab-bar in daemon's initial frame.
|
||||
;; Use `frame-initial-p'?
|
||||
(when (and (daemonp) (eq (selected-frame) terminal-frame))
|
||||
(setq parms (delq (assq 'tab-bar-lines parms) parms)))
|
||||
parms))
|
||||
|
|
|
|||
|
|
@ -1370,12 +1370,10 @@ All keyword parameters default to nil."
|
|||
;; frame, as that would only trigger
|
||||
;; warnings.
|
||||
(not
|
||||
(and (daemonp)
|
||||
(equal (terminal-name (frame-terminal
|
||||
frame))
|
||||
"initial_terminal"))))
|
||||
(delete-frame frame)))
|
||||
cleanup-frames)))
|
||||
(and (daemonp) ;; FIXME: Remove `daemonp'?
|
||||
(frame-initial-p frame))))
|
||||
(delete-frame frame)))
|
||||
cleanup-frames)))
|
||||
(maphash (lambda (frame _action) (push frame map)) frameset--action-map)
|
||||
(dolist (frame (sort map
|
||||
;; Minibufferless frames must go first to avoid
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ DELAY is a string, giving the length of the time. Possible values are:
|
|||
* YYYY-MM-DD for a specific date. The time of day is given by the
|
||||
variable `gnus-delay-default-hour', minute and second are zero.
|
||||
|
||||
* YYYY-MM-DD hh:mm(:ss) for a specific date and time. If seconds are left
|
||||
out, they will be zero.
|
||||
|
||||
* hh:mm for a specific time. Use 24h format. If it is later than this
|
||||
time, then the deadline is tomorrow, else today.
|
||||
|
||||
|
|
@ -82,8 +85,21 @@ generated when the article is sent."
|
|||
message-mode)
|
||||
;; Allow spell checking etc.
|
||||
(run-hooks 'message-send-hook)
|
||||
(let (num unit year month day hour minute deadline) ;; days
|
||||
(let (num unit year month day hour minute deadline second) ;; days
|
||||
(cond ((string-match
|
||||
"\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\) \\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\):?\\([0-9]\\{2\\}\\)?"
|
||||
delay)
|
||||
(setq year (string-to-number (match-string 1 delay))
|
||||
month (string-to-number (match-string 2 delay))
|
||||
day (string-to-number (match-string 3 delay))
|
||||
hour (string-to-number (match-string 4 delay))
|
||||
minute (string-to-number (match-string 5 delay))
|
||||
second (if (match-string 6 delay) (string-to-number (match-string 6 delay)) 0))
|
||||
(setq deadline
|
||||
(message-make-date
|
||||
(encode-time second minute hour
|
||||
day month year))))
|
||||
((string-match
|
||||
"\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\)"
|
||||
delay)
|
||||
(setq year (string-to-number (match-string 1 delay))
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@
|
|||
;;; Code:
|
||||
|
||||
(require 'icalendar)
|
||||
(require 'icalendar-parser)
|
||||
(eval-when-compile (require 'icalendar-macs))
|
||||
(require 'icalendar-ast)
|
||||
(require 'icalendar-utils)
|
||||
(require 'eieio)
|
||||
(require 'gmm-utils)
|
||||
(require 'mm-decode)
|
||||
|
|
@ -82,8 +86,8 @@
|
|||
:type (or null t))
|
||||
(recur :initarg :recur
|
||||
:accessor gnus-icalendar-event:recur
|
||||
:initform ""
|
||||
:type (or null string))
|
||||
:initform nil
|
||||
:type (or null list))
|
||||
(uid :initarg :uid
|
||||
:accessor gnus-icalendar-event:uid
|
||||
:type string)
|
||||
|
|
@ -127,295 +131,212 @@
|
|||
|
||||
(cl-defmethod gnus-icalendar-event:recurring-freq ((event gnus-icalendar-event))
|
||||
"Return recurring frequency of EVENT."
|
||||
(let ((rrule (gnus-icalendar-event:recur event)))
|
||||
(string-match "FREQ=\\([[:alpha:]]+\\)" rrule)
|
||||
(match-string 1 rrule)))
|
||||
(ical:recur-freq (gnus-icalendar-event:recur event)))
|
||||
|
||||
(cl-defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event))
|
||||
"Return recurring interval of EVENT."
|
||||
(let ((rrule (gnus-icalendar-event:recur event))
|
||||
(default-interval "1"))
|
||||
|
||||
(if (string-match "INTERVAL=\\([[:digit:]]+\\)" rrule)
|
||||
(match-string 1 rrule)
|
||||
default-interval)))
|
||||
(ical:recur-interval-size (gnus-icalendar-event:recur event)))
|
||||
|
||||
(cl-defmethod gnus-icalendar-event:recurring-days ((event gnus-icalendar-event))
|
||||
"Return, when available, the week day numbers on which the EVENT recurs."
|
||||
(let ((rrule (gnus-icalendar-event:recur event))
|
||||
(weekday-map '(("SU" . 0)
|
||||
("MO" . 1)
|
||||
("TU" . 2)
|
||||
("WE" . 3)
|
||||
("TH" . 4)
|
||||
("FR" . 5)
|
||||
("SA" . 6))))
|
||||
(when (and rrule (string-match "BYDAY=\\([^;]+\\)" rrule))
|
||||
(let ((bydays (split-string (match-string 1 rrule) ",")))
|
||||
(seq-map
|
||||
(lambda (x) (cdr (assoc x weekday-map)))
|
||||
(seq-filter (lambda (x) (string-match "^[A-Z]\\{2\\}$" x)) bydays))))))
|
||||
(let ((rrule (gnus-icalendar-event:recur event)))
|
||||
(when rrule
|
||||
(mapcar (lambda (el) (if (consp el) (car el) el))
|
||||
(ical:recur-by* 'BYDAY rrule)))))
|
||||
|
||||
(cl-defmethod gnus-icalendar-event:start ((event gnus-icalendar-event))
|
||||
(format-time-string "%Y-%m-%d %H:%M" (gnus-icalendar-event:start-time event)))
|
||||
|
||||
(defun gnus-icalendar-event--decode-datefield (event field zone-map)
|
||||
(let* ((dtdate (icalendar--get-event-property event field))
|
||||
(dtdate-zone (icalendar--find-time-zone
|
||||
(icalendar--get-event-property-attributes
|
||||
event field) zone-map))
|
||||
(dtdate-dec (icalendar--decode-isodatetime dtdate nil dtdate-zone)))
|
||||
(when dtdate-dec (encode-time dtdate-dec))))
|
||||
(defun gnus-icalendar-event--find-attendee (attendees ids)
|
||||
"Return the first `icalendar-attendee' in ATTENDEES matching IDS.
|
||||
IDS should be a list of strings. The first attendee is returned whose
|
||||
name (as `icalendar-cnparam') or email address (without \"mailto:\")
|
||||
is a member of IDS."
|
||||
(catch 'found
|
||||
(dolist (attendee attendees)
|
||||
(ical:with-property attendee ((ical:cnparam :value name))
|
||||
(let ((email (ical:strip-mailto value)))
|
||||
(when (or (member name ids)
|
||||
(member email ids))
|
||||
(throw 'found attendee)))))))
|
||||
|
||||
(defun gnus-icalendar-event--find-attendee (ical name-or-email)
|
||||
(let* ((event (car (icalendar--all-events ical)))
|
||||
(event-props (caddr event)))
|
||||
(cl-labels ((attendee-name (att) (plist-get (cadr att) 'CN))
|
||||
(attendee-email
|
||||
(att)
|
||||
(replace-regexp-in-string "^.*MAILTO:" "" (caddr att)))
|
||||
(attendee-prop-matches-p
|
||||
(prop)
|
||||
(and (eq (car prop) 'ATTENDEE)
|
||||
(or (member (attendee-name prop) name-or-email)
|
||||
(let ((att-email (attendee-email prop)))
|
||||
(gnus-icalendar-find-if
|
||||
(lambda (str-or-fun)
|
||||
(if (functionp str-or-fun)
|
||||
(funcall str-or-fun att-email)
|
||||
(string-match str-or-fun att-email)))
|
||||
name-or-email))))))
|
||||
(gnus-icalendar-find-if #'attendee-prop-matches-p event-props))))
|
||||
(defun gnus-icalendar-event--attendees-by-type (attendees)
|
||||
"Return lists of required and optional participants in ATTENDEES.
|
||||
ATTENDEES must be a list of `icalendar-attendee' nodes. The returned
|
||||
list has the form (REQUIRED OPTIONAL), where each is a list of
|
||||
`icalendar-attendee' nodes."
|
||||
(let (required optional)
|
||||
(dolist (attendee attendees)
|
||||
(ical:with-property attendee ((ical:roleparam :value role))
|
||||
(when (or (null role) ; "REQ-PARTICIPANT" is the default
|
||||
(equal role "REQ-PARTICIPANT"))
|
||||
(push attendee required))
|
||||
(when (equal role "OPT-PARTICIPANT")
|
||||
(push attendee optional))))
|
||||
(list (nreverse required)
|
||||
(nreverse optional))))
|
||||
|
||||
(defun gnus-icalendar-event--get-attendee-names (ical)
|
||||
(let* ((event (car (icalendar--all-events ical)))
|
||||
(attendee-props (seq-filter
|
||||
(lambda (p) (eq (car p) 'ATTENDEE))
|
||||
(caddr event))))
|
||||
(defun gnus-icalendar-event-from-ical (vcalendar &optional ids)
|
||||
"Initialize an event instance with the first `icalendar-vevent' in VCALENDAR.
|
||||
IDS should be a list of strings representing names and email addresses
|
||||
by which to identify an `icalendar-attendee' in the event as the
|
||||
recipient."
|
||||
(ical:with-component vcalendar
|
||||
((ical:vevent vevent)
|
||||
(ical:method :value method))
|
||||
(ical:with-component vevent
|
||||
((ical:organizer :value organizer)
|
||||
(ical:attendee :all attendees)
|
||||
(ical:summary :value summary)
|
||||
(ical:description :value description)
|
||||
(ical:dtstart :value dtstart)
|
||||
(ical:dtend :value dtend)
|
||||
(ical:location :value location)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:uid :value uid))
|
||||
|
||||
(cl-labels
|
||||
((attendee-role (prop)
|
||||
;; RFC5546: default ROLE is REQ-PARTICIPANT
|
||||
(and prop
|
||||
(or (plist-get (cadr prop) 'ROLE)
|
||||
"REQ-PARTICIPANT")))
|
||||
(attendee-name
|
||||
(prop)
|
||||
(or (plist-get (cadr prop) 'CN)
|
||||
(replace-regexp-in-string "^.*MAILTO:" "" (caddr prop))))
|
||||
(attendees-by-type (type)
|
||||
(seq-filter
|
||||
(lambda (p) (string= (attendee-role p) type))
|
||||
attendee-props))
|
||||
(attendee-names-by-type
|
||||
(type)
|
||||
(mapcar #'attendee-name (attendees-by-type type))))
|
||||
(list
|
||||
(attendee-names-by-type "REQ-PARTICIPANT")
|
||||
(attendee-names-by-type "OPT-PARTICIPANT")))))
|
||||
|
||||
(defun gnus-icalendar-event-from-ical (ical &optional attendee-name-or-email)
|
||||
(let* ((event (car (icalendar--all-events ical)))
|
||||
(organizer (replace-regexp-in-string
|
||||
"^.*MAILTO:" ""
|
||||
(or (icalendar--get-event-property event 'ORGANIZER) "")))
|
||||
(prop-map '((summary . SUMMARY)
|
||||
(description . DESCRIPTION)
|
||||
(location . LOCATION)
|
||||
(recur . RRULE)
|
||||
(uid . UID)))
|
||||
(method (caddr (assoc 'METHOD (caddr (car (nreverse ical))))))
|
||||
(attendee (when attendee-name-or-email
|
||||
(gnus-icalendar-event--find-attendee
|
||||
ical attendee-name-or-email)))
|
||||
(attendee-names (gnus-icalendar-event--get-attendee-names ical))
|
||||
(let* ((attendee (when ids (gnus-icalendar-event--find-attendee attendees ids)))
|
||||
(rsvp-p (ical:with-param-of attendee 'ical:rsvpparam))
|
||||
;; RFC5546: default ROLE is REQ-PARTICIPANT
|
||||
(role (and attendee
|
||||
(or (plist-get (cadr attendee) 'ROLE)
|
||||
"REQ-PARTICIPANT")))
|
||||
(role (when attendee
|
||||
(or (ical:with-param-of attendee 'ical:roleparam)
|
||||
"REQ-PARTICIPANT")))
|
||||
(participation-type (pcase role
|
||||
("REQ-PARTICIPANT" 'required)
|
||||
("OPT-PARTICIPANT" 'optional)
|
||||
(_ 'non-participant)))
|
||||
(zone-map (icalendar--convert-all-timezones ical))
|
||||
(req/opt (gnus-icalendar-event--attendees-by-type attendees))
|
||||
(args
|
||||
(list :method method
|
||||
:organizer organizer
|
||||
:start-time (gnus-icalendar-event--decode-datefield
|
||||
event 'DTSTART zone-map)
|
||||
:end-time (gnus-icalendar-event--decode-datefield
|
||||
event 'DTEND zone-map)
|
||||
:rsvp (string= (plist-get (cadr attendee) 'RSVP) "TRUE")
|
||||
:organizer (when organizer (ical:strip-mailto organizer))
|
||||
:summary summary
|
||||
:description description
|
||||
:location location
|
||||
:recur rrule
|
||||
:start-time (encode-time dtstart)
|
||||
:end-time (encode-time dtend)
|
||||
:rsvp rsvp-p
|
||||
:participation-type participation-type
|
||||
:req-participants (car attendee-names)
|
||||
:opt-participants (cadr attendee-names)))
|
||||
(event-class
|
||||
(cond
|
||||
((string= method "REQUEST") 'gnus-icalendar-event-request)
|
||||
((string= method "CANCEL") 'gnus-icalendar-event-cancel)
|
||||
((string= method "REPLY") 'gnus-icalendar-event-reply)
|
||||
(t 'gnus-icalendar-event))))
|
||||
(cl-labels
|
||||
((map-property
|
||||
(prop)
|
||||
(let ((value (icalendar--get-event-property event prop)))
|
||||
(when value
|
||||
;; ugly, but cannot get
|
||||
;;replace-regexp-in-string work with "\\" as
|
||||
;;REP, plus we should also handle "\\;"
|
||||
(string-replace
|
||||
"\\," ","
|
||||
(string-replace
|
||||
"\\n" "\n" (substring-no-properties value))))))
|
||||
(accumulate-args
|
||||
(mapping)
|
||||
(cl-destructuring-bind (slot . ical-property) mapping
|
||||
(setq args (append (list
|
||||
(intern (concat ":" (symbol-name slot)))
|
||||
(map-property ical-property))
|
||||
args)))))
|
||||
(mapc #'accumulate-args prop-map)
|
||||
(apply
|
||||
#'make-instance
|
||||
event-class
|
||||
(cl-loop for slot in (eieio-class-slots event-class)
|
||||
for keyword = (intern
|
||||
(format ":%s" (eieio-slot-descriptor-name slot)))
|
||||
when (plist-member args keyword)
|
||||
append (list keyword
|
||||
(if (eq keyword :uid)
|
||||
;; The UID has to be a string.
|
||||
(or (plist-get args keyword) "")
|
||||
(plist-get args keyword))))))))
|
||||
:req-participants (car req/opt)
|
||||
:opt-participants (cadr req/opt)
|
||||
:uid (or uid ""))) ; UID must be a string
|
||||
(event-class (pcase method
|
||||
("REQUEST" 'gnus-icalendar-event-request)
|
||||
("CANCEL" 'gnus-icalendar-event-cancel)
|
||||
("REPLY" 'gnus-icalendar-event-reply)
|
||||
(_ 'gnus-icalendar-event))))
|
||||
;; Initialize and return the instance:
|
||||
(apply
|
||||
#'make-instance
|
||||
event-class
|
||||
(cl-loop for slot in (eieio-class-slots event-class)
|
||||
for keyword = (intern
|
||||
(format ":%s" (eieio-slot-descriptor-name slot)))
|
||||
when (plist-member args keyword)
|
||||
append (list keyword (plist-get args keyword))))))))
|
||||
|
||||
(defun gnus-icalendar-event-from-buffer (buf &optional attendee-name-or-email)
|
||||
(defun gnus-icalendar-event-from-buffer (buf &optional ids)
|
||||
"Parse RFC5545 iCalendar in buffer BUF and return an event object.
|
||||
|
||||
Return a gnus-icalendar-event object representing the first event
|
||||
contained in the invitation. Return nil for calendars without an
|
||||
event entry.
|
||||
|
||||
ATTENDEE-NAME-OR-EMAIL is a list of strings that will be matched
|
||||
against the event's attendee names and emails. Invitation rsvp
|
||||
status will be retrieved from the first matching attendee record."
|
||||
(let ((ical (with-current-buffer (icalendar--get-unfolded-buffer (get-buffer buf))
|
||||
(goto-char (point-min))
|
||||
(icalendar--read-element nil nil))))
|
||||
|
||||
(when ical
|
||||
(gnus-icalendar-event-from-ical ical attendee-name-or-email))))
|
||||
IDS is a list of strings that identify the recipient
|
||||
`icalendar-attendee' by name or email address. Invitation rsvp status
|
||||
will be retrieved from the first matching attendee record."
|
||||
(let ((vcalendar (ical:parse buf)))
|
||||
(when vcalendar
|
||||
(gnus-icalendar-event-from-ical vcalendar ids))))
|
||||
|
||||
;;;
|
||||
;;; gnus-icalendar-event-reply
|
||||
;;;
|
||||
|
||||
(defun gnus-icalendar-event--build-reply-event-body (ical-request status identities &optional comment)
|
||||
(defun gnus-icalendar-event--build-reply (vcalendar status ids &optional comment)
|
||||
"Return an `icalendar-vcalendar' based on VCALENDAR with updated STATUS.
|
||||
STATUS should one of \\='accepted, \\='declined, or \\='tentative. The
|
||||
recipient whose participation status is updated to STATUS is identified
|
||||
in EVENT by finding an `icalendar-attendee' whose name or email address
|
||||
matches one of the strings in IDS. If no such attendee is found, a new
|
||||
`icalendar-attendee' is added from the values of `user-mail-address' and
|
||||
`user-full-name'. COMMENT, if provided, will be added as an
|
||||
`icalendar-comment' to the returned event."
|
||||
(let ((summary-status (capitalize (symbol-name status)))
|
||||
(attendee-status (upcase (symbol-name status)))
|
||||
reply-event-lines)
|
||||
(cl-labels
|
||||
((update-summary
|
||||
(line)
|
||||
(if (string-match "^[^:]+:" line)
|
||||
(replace-match (format "\\&%s: " summary-status) t nil line)
|
||||
line))
|
||||
(update-comment
|
||||
(line)
|
||||
(if comment (format "COMMENT:%s" comment)
|
||||
line))
|
||||
(update-dtstamp ()
|
||||
(format-time-string "DTSTAMP:%Y%m%dT%H%M%SZ" nil t))
|
||||
(attendee-matches-identity
|
||||
(line)
|
||||
(gnus-icalendar-find-if (lambda (name) (string-match-p name line))
|
||||
identities))
|
||||
(update-attendee-status
|
||||
(line)
|
||||
(when (and (attendee-matches-identity line)
|
||||
(string-match "\\(PARTSTAT=\\)[^;]+" line))
|
||||
(replace-match (format "\\1%s" attendee-status) t nil line)))
|
||||
(process-event-line
|
||||
(line)
|
||||
(when (string-match "^\\([^;:]+\\)" line)
|
||||
(let* ((key (match-string 0 line))
|
||||
;; NOTE: not all of the below fields are mandatory,
|
||||
;; but they are often present in other clients'
|
||||
;; replies. Can be helpful for debugging, too.
|
||||
(new-line
|
||||
(cond
|
||||
((string= key "ATTENDEE") (update-attendee-status line))
|
||||
((string= key "SUMMARY") (update-summary line))
|
||||
((string= key "COMMENT") (update-comment line))
|
||||
((string= key "DTSTAMP") (update-dtstamp))
|
||||
((member key '("ORGANIZER" "DTSTART" "DTEND"
|
||||
"LOCATION" "DURATION" "SEQUENCE"
|
||||
"RECURRENCE-ID" "UID"))
|
||||
line)
|
||||
(t nil))))
|
||||
(when new-line
|
||||
(push new-line reply-event-lines))))))
|
||||
recipient)
|
||||
(ical:with-component vcalendar
|
||||
((ical:vtimezone :all tz-nodes)
|
||||
(ical:vevent :first vevent))
|
||||
(ical:with-component vevent
|
||||
((ical:summary :value summary)
|
||||
(ical:attendee :all attendees)
|
||||
(ical:uid :value uid)
|
||||
(ical:comment :value old-comment)
|
||||
;; The nodes below are copied unchanged to the reply. Not all
|
||||
;; of them are mandatory, but they are often present in other
|
||||
;; clients' replies. Can be helpful for debugging, too.
|
||||
(ical:organizer :first organizer-node)
|
||||
(ical:dtstart :first dtstart-node)
|
||||
(ical:dtend :first dtend-node)
|
||||
(ical:duration :first duration-node)
|
||||
(ical:location :first location-node)
|
||||
(ical:sequence :first sequence-node)
|
||||
(ical:recurrence-id :first recid-node))
|
||||
|
||||
(mapc #'process-event-line (split-string ical-request "\n"))
|
||||
(setq recipient (gnus-icalendar-event--find-attendee attendees ids))
|
||||
(if recipient
|
||||
(ical:with-property recipient
|
||||
((ical:partstatparam :first partstat-node))
|
||||
(ical:ast-node-set-value partstat-node attendee-status))
|
||||
;; RFC5546 refers to uninvited attendees as "party crashers".
|
||||
;; This situation is common if the invitation is sent to a group
|
||||
;; of people via a mailing list.
|
||||
(lwarn 'gnus-icalendar :warning
|
||||
"Could not find a matching event attendee; creating new.")
|
||||
(setq recipient
|
||||
(ical:make-property ical:attendee
|
||||
(concat "mailto:" user-mail-address)
|
||||
(ical:partstatparam attendee-status)
|
||||
(ical:cnparam user-full-name)))
|
||||
(push recipient attendees))
|
||||
|
||||
;; RFC5546 refers to uninvited attendees as "party crashers".
|
||||
;; This situation is common if the invitation is sent to a group
|
||||
;; of people via a mailing list.
|
||||
(unless (gnus-icalendar-find-if (lambda (x) (string-match "^ATTENDEE" x))
|
||||
reply-event-lines)
|
||||
(lwarn 'gnus-icalendar :warning
|
||||
"Could not find an event attendee matching given identity")
|
||||
(push (format "ATTENDEE;RSVP=TRUE;PARTSTAT=%s;CN=%s:MAILTO:%s"
|
||||
attendee-status user-full-name user-mail-address)
|
||||
reply-event-lines))
|
||||
;; Build the reply:
|
||||
(ical:make-vcalendar
|
||||
(ical:method "REPLY")
|
||||
(@ tz-nodes)
|
||||
(ical:vevent
|
||||
(ical:uid uid)
|
||||
recid-node
|
||||
sequence-node
|
||||
organizer-node
|
||||
dtstart-node
|
||||
dtend-node
|
||||
duration-node
|
||||
location-node
|
||||
(ical:summary
|
||||
(if (string-match "^[^:]+:" summary)
|
||||
(replace-match (format "\\&%s: " summary-status) t nil summary)
|
||||
summary))
|
||||
(ical:comment (or comment old-comment))
|
||||
(@ attendees)))))))
|
||||
|
||||
;; add comment line if not existing
|
||||
(when (and comment
|
||||
(not (gnus-icalendar-find-if
|
||||
(lambda (x)
|
||||
(string-match "^COMMENT" x))
|
||||
reply-event-lines)))
|
||||
(push (format "COMMENT:%s" comment) reply-event-lines))
|
||||
|
||||
(mapconcat #'identity `("BEGIN:VEVENT"
|
||||
,@(nreverse reply-event-lines)
|
||||
"END:VEVENT")
|
||||
"\n"))))
|
||||
|
||||
(defun gnus-icalendar-event-reply-from-buffer (buf status identities &optional comment)
|
||||
(defun gnus-icalendar-event-reply-from-buffer (buf status ids
|
||||
&optional comment)
|
||||
"Build a calendar event reply for request contained in BUF.
|
||||
The reply will have STATUS (`accepted', `tentative' or `declined').
|
||||
The reply will be composed for attendees matching any entry
|
||||
on the IDENTITIES list.
|
||||
Optional argument COMMENT will be placed in the comment field of the
|
||||
reply.
|
||||
"
|
||||
(cl-labels
|
||||
((extract-block
|
||||
(blockname)
|
||||
(save-excursion
|
||||
(let ((block-start-re (format "^BEGIN:%s" blockname))
|
||||
(block-end-re (format "^END:%s" blockname))
|
||||
start)
|
||||
(when (re-search-forward block-start-re nil t)
|
||||
(setq start (line-beginning-position))
|
||||
(re-search-forward block-end-re)
|
||||
(buffer-substring-no-properties start (line-end-position)))))))
|
||||
(let (zone event)
|
||||
(with-current-buffer (icalendar--get-unfolded-buffer (get-buffer buf))
|
||||
(goto-char (point-min))
|
||||
(setq zone (extract-block "VTIMEZONE")
|
||||
event (extract-block "VEVENT")))
|
||||
|
||||
(when event
|
||||
(let ((contents (list "BEGIN:VCALENDAR"
|
||||
"METHOD:REPLY"
|
||||
"PRODID:Gnus"
|
||||
"VERSION:2.0"
|
||||
zone
|
||||
(gnus-icalendar-event--build-reply-event-body event status identities comment)
|
||||
"END:VCALENDAR")))
|
||||
|
||||
(mapconcat #'identity (delq nil contents) "\n"))))))
|
||||
The reply will have STATUS (`accepted', `tentative' or `declined'). The
|
||||
reply will be composed for attendees matching any entry in the
|
||||
IDS list. Optional argument COMMENT will be placed in the
|
||||
comment field of the reply."
|
||||
(let (vcalendar reply)
|
||||
(with-current-buffer (ical:unfolded-buffer-from-buffer (get-buffer buf))
|
||||
(setq vcalendar (ical:parse))
|
||||
(unless vcalendar
|
||||
(error "Could not parse invitation; see buffer %s"
|
||||
(buffer-name (ical:error-buffer))))
|
||||
(setq reply
|
||||
(gnus-icalendar-event--build-reply vcalendar status ids comment))
|
||||
(ical:print-calendar-node reply))))
|
||||
|
||||
;;;
|
||||
;;; gnus-icalendar-org
|
||||
|
|
@ -455,15 +376,17 @@ reply.
|
|||
"Return `org-mode' timestamp repeater string for recurring EVENT.
|
||||
Return nil for non-recurring EVENT."
|
||||
(when (gnus-icalendar-event:recurring-p event)
|
||||
(let* ((freq-map '(("HOURLY" . "h")
|
||||
("DAILY" . "d")
|
||||
("WEEKLY" . "w")
|
||||
("MONTHLY" . "m")
|
||||
("YEARLY" . "y")))
|
||||
(org-freq (cdr (assoc (gnus-icalendar-event:recurring-freq event) freq-map))))
|
||||
(let* ((freq-map '((HOURLY . "h")
|
||||
(DAILY . "d")
|
||||
(WEEKLY . "w")
|
||||
(MONTHLY . "m")
|
||||
(YEARLY . "y")))
|
||||
(org-freq
|
||||
(alist-get (gnus-icalendar-event:recurring-freq event) freq-map))
|
||||
(interval-size (gnus-icalendar-event:recurring-interval event)))
|
||||
|
||||
(when org-freq
|
||||
(format "+%s%s" (gnus-icalendar-event:recurring-interval event) org-freq)))))
|
||||
(format "+%d%s" interval-size org-freq)))))
|
||||
|
||||
(defun gnus-icalendar--find-day (start-date end-date day)
|
||||
(let ((time-1-day 86400))
|
||||
|
|
@ -550,7 +473,18 @@ Return nil for non-recurring EVENT."
|
|||
|
||||
|
||||
(defun gnus-icalendar--format-participant-list (participants)
|
||||
(mapconcat #'identity participants ", "))
|
||||
"Format PARTICIPANTS as a comma-separated list.
|
||||
|
||||
Each `icalendar-attendee' in PARTICIPANTS will be represented like
|
||||
A. Person <a.person@example.domain>
|
||||
or simply: <a.person@example.domain>, if no `icalendar-cnparam' is present."
|
||||
(mapconcat
|
||||
(lambda (attendee)
|
||||
(ical:with-property attendee ((ical:cnparam :value cn))
|
||||
(if cn
|
||||
(format "%s <%s>" cn value)
|
||||
(format "<%s>" value))))
|
||||
participants ", "))
|
||||
|
||||
;; TODO: make the template customizable
|
||||
(cl-defmethod gnus-icalendar-event->org-entry ((event gnus-icalendar-event) reply-status)
|
||||
|
|
@ -1110,3 +1044,7 @@ means prompt for a comment to include in the reply."
|
|||
(provide 'gnus-icalendar)
|
||||
|
||||
;;; gnus-icalendar.el ends here
|
||||
|
||||
;; Local Variables:
|
||||
;; read-symbol-shorthands: (("ical:" . "icalendar-"))
|
||||
;; End:
|
||||
|
|
|
|||
12
lisp/help.el
12
lisp/help.el
|
|
@ -2356,11 +2356,13 @@ ARGLIST can also be t or a string of the form \"(FUN ARG1 ARG2 ...)\"."
|
|||
"Return a formal argument list for the function DEF.
|
||||
If PRESERVE-NAMES is non-nil, return a formal arglist that uses
|
||||
the same names as used in the original source code, when possible."
|
||||
(let ((orig-def def)
|
||||
;; Advice wrappers have "catch all" args, so fetch the actual underlying
|
||||
;; function to find the real arguments.
|
||||
(def (advice--cd*r
|
||||
(indirect-function def)))) ;; Follow aliases to other symbols.
|
||||
(let ((orig-def def))
|
||||
(let ((seen nil))
|
||||
;; Advice wrappers have "catch all" args, so fetch the actual underlying
|
||||
;; function to find the real arguments. Also follow aliases.
|
||||
(while (not (memq def seen))
|
||||
(push def seen)
|
||||
(setq def (advice--cd*r (indirect-function def)))))
|
||||
;; If definition is a macro, find the function inside it.
|
||||
(if (eq (car-safe def) 'macro) (setq def (cdr def)))
|
||||
(cond
|
||||
|
|
|
|||
11
lisp/info.el
11
lisp/info.el
|
|
@ -1897,8 +1897,10 @@ of NODENAME; if none is found it then tries a case-insensitive match
|
|||
(if (equal nodename "") "Top" nodename) nil strict-case)))
|
||||
|
||||
(defun Info-goto-node-web (node)
|
||||
"Use `browse-url' to go to the gnu.org web server's version of NODE.
|
||||
By default, go to the current Info node."
|
||||
"Use `browse-url' to go to the gnu.org Web server's version of NODE.
|
||||
By default, go to the URL corresponding to the current Info node.
|
||||
|
||||
This uses `Info-url-for-node' to determine the URL that corresponds to NODE."
|
||||
(interactive (list (Info-read-node-name
|
||||
"Go to node (default current page): " Info-current-node))
|
||||
Info-mode)
|
||||
|
|
@ -1924,7 +1926,10 @@ By default, go to the current Info node."
|
|||
(defun Info-url-for-node (node)
|
||||
"Return the URL corresponding to NODE.
|
||||
|
||||
NODE should be a string of the form \"(manual)Node\"."
|
||||
NODE should be a string of the form \"(manual)Node\".
|
||||
|
||||
The correspondence between Info manuals and their Web URLs is
|
||||
established by `Info-url-alist', which see."
|
||||
;; GNU Texinfo skips whitespaces and newlines between the closing
|
||||
;; parenthesis and the node-name, i.e. space, tab, line feed and
|
||||
;; carriage return.
|
||||
|
|
|
|||
|
|
@ -1782,15 +1782,15 @@ Setup `char-width-table' appropriate for non-CJK language environment."
|
|||
(let ((c0-acronyms '("NUL" "SOH" "STX" "ETX" "EOT" "ENQ" "ACK" "BEL"
|
||||
"BS" nil nil "VT" "FF" "CR" "SO" "SI"
|
||||
"DLE" "DC1" "DC2" "DC3" "DC4" "NAK" "SYN" "ETB"
|
||||
"CAN" "EM" "SUB" "ESC" "FC" "GS" "RS" "US")))
|
||||
"CAN" "EM" "SUB" "ESC" "FS" "GS" "RS" "US")))
|
||||
(dotimes (i 32)
|
||||
(aset char-acronym-table i (car c0-acronyms))
|
||||
(setq c0-acronyms (cdr c0-acronyms))))
|
||||
|
||||
(let ((c1-acronyms '("PAD" "HOP" "BPH" "NBH" "IND" "NEL" "SSA" "ESA"
|
||||
"HTS" "HTJ" "VTS" "PLD" "PLU" "R1" "SS2" "SS1"
|
||||
"HTS" "HTJ" "VTS" "PLD" "PLU" "RI" "SS2" "SS3"
|
||||
"DCS" "PU1" "PU2" "STS" "CCH" "MW" "SPA" "EPA"
|
||||
"SOS" "SGCI" "SC1" "CSI" "ST" "OSC" "PM" "APC")))
|
||||
"SOS" "SGCI" "SCI" "CSI" "ST" "OSC" "PM" "APC")))
|
||||
(dotimes (i 32)
|
||||
(aset char-acronym-table (+ #x0080 i) (car c1-acronyms))
|
||||
(setq c1-acronyms (cdr c1-acronyms))))
|
||||
|
|
|
|||
|
|
@ -155,9 +155,13 @@ and also consults the `emoji-alternate-names' alist."
|
|||
|
||||
;;;###autoload
|
||||
(defun emoji-list ()
|
||||
"List emojis and allow selecting and inserting one of them.
|
||||
"List Emoji and allow selecting and inserting one of them.
|
||||
If you are displaying Emoji on a text-only terminal, and some
|
||||
of them look incorrect, or there are display artifacts when
|
||||
scrolling the display, turn off `auto-composition-mode'.
|
||||
|
||||
Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its picture.
|
||||
The glyph will be inserted into the buffer that was current
|
||||
The selected glyph will be inserted into the buffer that was current
|
||||
when the command was invoked."
|
||||
(interactive)
|
||||
(let ((buf (current-buffer)))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
;; Author: João Távora <joaotavora@gmail.com>
|
||||
;; Keywords: processes, languages, extensions
|
||||
;; Version: 1.0.27
|
||||
;; Version: 1.0.28
|
||||
;; Package-Requires: ((emacs "25.2"))
|
||||
|
||||
;; This is a GNU ELPA :core package. Avoid functionality that is not
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ macro to be executed before appending to it."
|
|||
;;;###autoload (autoload 'kmacro-keymap "kmacro" "Keymap for keyboard macro commands." t 'keymap)
|
||||
|
||||
(if kmacro-call-mouse-event
|
||||
(global-set-key (vector kmacro-call-mouse-event) #'kmacro-end-call-mouse))
|
||||
(global-set-key (vector kmacro-call-mouse-event) #'kmacro-end-and-call-macro))
|
||||
|
||||
|
||||
;;; Called from keyboard-quit
|
||||
|
|
@ -742,8 +742,8 @@ With numeric ARG, repeat the macro that many times,
|
|||
counting the definition just completed as the first repetition.
|
||||
An argument of zero means repeat until error."
|
||||
(interactive "p")
|
||||
;; Isearch may push the kmacro-end-macro key sequence onto the macro.
|
||||
;; Just ignore it when executing the macro.
|
||||
;; Isearch may push the kmacro-end-macro key sequence onto the macro.
|
||||
;; Just ignore it when executing the macro. FIXME: When?Why?
|
||||
(unless executing-kbd-macro
|
||||
(end-kbd-macro arg #'kmacro-loop-setup-function)
|
||||
(when (and last-kbd-macro (= (length last-kbd-macro) 0))
|
||||
|
|
@ -880,35 +880,25 @@ With \\[universal-argument], call second macro in macro ring."
|
|||
|
||||
|
||||
;;;###autoload
|
||||
(defun kmacro-end-and-call-macro (arg &optional no-repeat)
|
||||
(defun kmacro-end-and-call-macro (arg &optional no-repeat event)
|
||||
"Call last keyboard macro, ending it first if currently being defined.
|
||||
With numeric prefix ARG, repeat macro that many times.
|
||||
Zero argument means repeat until there is an error.
|
||||
If triggered via a mouse EVENT, moves point to the position clicked
|
||||
with the mouse before calling the macro.
|
||||
|
||||
To give a macro a name, so you can call it even after defining other
|
||||
macros, use \\[kmacro-name-last-macro]."
|
||||
(interactive "p")
|
||||
(interactive (list current-prefix-arg nil
|
||||
(if (consp last-input-event) last-input-event)))
|
||||
(if defining-kbd-macro
|
||||
(kmacro-end-macro nil))
|
||||
(if event (mouse-set-point event))
|
||||
(kmacro-call-macro arg no-repeat))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun kmacro-end-call-mouse (event)
|
||||
"Move point to the position clicked with the mouse and call last kbd macro.
|
||||
If kbd macro currently being defined end it before activating it."
|
||||
(interactive "e")
|
||||
(when defining-kbd-macro
|
||||
(end-kbd-macro)
|
||||
(when (and last-kbd-macro (= (length last-kbd-macro) 0))
|
||||
(setq last-kbd-macro nil)
|
||||
(message "Ignore empty macro")
|
||||
;; Don't call `kmacro-ring-empty-p' to avoid its messages.
|
||||
(while (and (null last-kbd-macro) kmacro-ring)
|
||||
(kmacro-pop-ring1))))
|
||||
(mouse-set-point event)
|
||||
(kmacro-call-macro nil t))
|
||||
|
||||
(define-obsolete-function-alias 'kmacro-end-call-mouse
|
||||
#'kmacro-end-and-call-macro "31.1")
|
||||
|
||||
;;; Misc. commands
|
||||
|
||||
|
|
|
|||
|
|
@ -27,13 +27,22 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(defgroup korean nil
|
||||
"Options for writing Korean."
|
||||
:version "31.1"
|
||||
:group 'languages)
|
||||
|
||||
;;;###autoload
|
||||
(defvar default-korean-keyboard
|
||||
(defcustom default-korean-keyboard
|
||||
(if (string-search "3" (or (getenv "HANGUL_KEYBOARD_TYPE") ""))
|
||||
"3"
|
||||
"")
|
||||
"The kind of Korean keyboard for Korean (Hangul) input method.
|
||||
\"\" for 2, \"3\" for 3, and \"3f\" for 3f.")
|
||||
\"\" for 2, \"3\" for 3, and \"3f\" for 3f."
|
||||
:initialize #'custom-initialize-delay
|
||||
:group 'korean
|
||||
:version "31.1"
|
||||
:type 'string)
|
||||
|
||||
;; functions useful for Korean text input
|
||||
|
||||
|
|
|
|||
|
|
@ -231,8 +231,8 @@ in the tool bar will close the current window where possible."
|
|||
'(menu-item "Open Project Directory" project-dired
|
||||
:enable (menu-bar-non-minibuffer-window-p)
|
||||
:help "Read the root directory of the current project, to operate on its files"))
|
||||
(define-key menu [dired]
|
||||
'(menu-item "Open Directory..." dired
|
||||
(define-key menu [open-directory]
|
||||
'(menu-item "Open Directory..." dired-from-menubar
|
||||
:enable (menu-bar-non-minibuffer-window-p)
|
||||
:help "Read a directory, to operate on its files"))
|
||||
(define-key menu [project-open-file]
|
||||
|
|
@ -2287,7 +2287,7 @@ this frame."
|
|||
(and menu-bar-close-window
|
||||
(window-parent (selected-window)))))
|
||||
|
||||
(put 'dired 'menu-enable '(menu-bar-non-minibuffer-window-p))
|
||||
(put 'dired-from-menubar 'menu-enable '(menu-bar-non-minibuffer-window-p))
|
||||
|
||||
;; Permit deleting frame if it would leave a visible or iconified frame.
|
||||
(defun delete-frame-enabled-p ()
|
||||
|
|
@ -2496,8 +2496,7 @@ It must accept a buffer as its only required argument.")
|
|||
;; Ignore the initial frame if present. It can happen if
|
||||
;; Emacs was started as a daemon. (bug#53740)
|
||||
(dolist (frame (frame-list))
|
||||
(unless (equal (terminal-name (frame-terminal frame))
|
||||
"initial_terminal")
|
||||
(unless (frame-initial-p frame)
|
||||
(push frame frames)))
|
||||
;; Make the menu of buffers proper.
|
||||
(setq buffers-menu
|
||||
|
|
|
|||
|
|
@ -2807,7 +2807,7 @@ has been requested by the completion table."
|
|||
"Update displayed *Completions* buffer after change in buffer contents."
|
||||
(if (not (or (minibufferp nil t) completion-in-region-mode))
|
||||
(remove-hook 'after-change-functions #'completions--after-change t)
|
||||
(when-let* ((window (get-buffer-window "*Completions*" 0)))
|
||||
(when-let* ((window (get-buffer-window "*Completions*" 'visible)))
|
||||
(when completion-auto-deselect
|
||||
(with-selected-window window
|
||||
(completions--deselect))))
|
||||
|
|
@ -3480,7 +3480,7 @@ in the minibuffer window."
|
|||
|
||||
(defun minibuffer--completions-visible ()
|
||||
"Return the window where the current *Completions* buffer is visible, if any."
|
||||
(when-let* ((window (get-buffer-window "*Completions*" 0)))
|
||||
(when-let* ((window (get-buffer-window "*Completions*" 'visible)))
|
||||
(let ((reference-buffer
|
||||
(buffer-local-value 'completion-reference-buffer
|
||||
(window-buffer window))))
|
||||
|
|
|
|||
|
|
@ -870,7 +870,8 @@ t if it successfully authenticates, nil otherwise."
|
|||
(base64-encode-string
|
||||
(format "\000%s\000%s"
|
||||
(imap-quote-specials user)
|
||||
(imap-quote-specials passwd)))))))))
|
||||
(imap-quote-specials passwd))
|
||||
t)))))))
|
||||
|
||||
(defun imap-anonymous-p (_buffer)
|
||||
t)
|
||||
|
|
|
|||
|
|
@ -451,21 +451,13 @@ Emacs dired can't find files."
|
|||
(defun tramp-adb-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(all-completions
|
||||
filename
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(with-tramp-file-property v localname "file-name-all-completions"
|
||||
(when (tramp-adb-do-ls v "-a" localname)
|
||||
(mapcar
|
||||
(lambda (f)
|
||||
(if (file-directory-p (expand-file-name f directory))
|
||||
(file-name-as-directory f)
|
||||
f))
|
||||
(with-current-buffer (tramp-get-buffer v)
|
||||
(mapcar
|
||||
(lambda (l)
|
||||
(and (not (string-match-p (rx bol (* blank) eol) l)) l))
|
||||
(split-string (buffer-string) "\n" 'omit))))))))))
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(when (tramp-adb-do-ls v "-a" localname)
|
||||
(with-current-buffer (tramp-get-buffer v)
|
||||
(mapcar
|
||||
(lambda (l)
|
||||
(and (not (string-match-p (rx bol (* blank) eol) l)) l))
|
||||
(split-string (buffer-string) "\n" 'omit)))))))
|
||||
|
||||
(defun tramp-adb-handle-file-local-copy (filename)
|
||||
"Like `file-local-copy' for Tramp files."
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ BODY is the backend specific code."
|
|||
tramp--last-hop-directory)
|
||||
tramp-compat-temporary-file-directory))
|
||||
(program (let ((tramp-verbose 0))
|
||||
(tramp-get-method-parameter
|
||||
(tramp-expand-args
|
||||
(make-tramp-file-name :method ,method)
|
||||
'tramp-login-program)))
|
||||
(vec (when (tramp-tramp-file-p default-directory)
|
||||
|
|
@ -656,10 +656,9 @@ see its function help for a description of the format."
|
|||
'((tramp-config-check . tramp-kubernetes--current-context-data)
|
||||
;; This variable will be eval'ed in `tramp-expand-args'.
|
||||
(tramp-extra-expand-args
|
||||
. (?a (tramp-kubernetes--container (car tramp-current-connection))
|
||||
?h (tramp-kubernetes--pod (car tramp-current-connection))
|
||||
?x (tramp-kubernetes--context-namespace
|
||||
(car tramp-current-connection)))))
|
||||
?a (tramp-kubernetes--container (car tramp-current-connection))
|
||||
?h (tramp-kubernetes--pod (car tramp-current-connection))
|
||||
?x (tramp-kubernetes--context-namespace (car tramp-current-connection))))
|
||||
"Default connection-local variables for remote kubernetes connections.")
|
||||
|
||||
(connection-local-set-profile-variables
|
||||
|
|
|
|||
|
|
@ -741,18 +741,16 @@ absolute file names."
|
|||
(defun tramp-crypt-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(all-completions
|
||||
filename
|
||||
(let* (completion-regexp-list
|
||||
tramp-crypt-enabled
|
||||
(directory (file-name-as-directory directory))
|
||||
(enc-dir (tramp-crypt-encrypt-file-name directory)))
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(substring
|
||||
(tramp-crypt-decrypt-file-name (concat enc-dir x))
|
||||
(length directory)))
|
||||
(file-name-all-completions "" enc-dir))))))
|
||||
(let* (completion-regexp-list
|
||||
tramp-crypt-enabled
|
||||
(directory (file-name-as-directory directory))
|
||||
(enc-dir (tramp-crypt-encrypt-file-name directory)))
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(substring
|
||||
(tramp-crypt-decrypt-file-name (concat enc-dir x))
|
||||
(length directory)))
|
||||
(file-name-all-completions "" enc-dir)))))
|
||||
|
||||
(defun tramp-crypt-handle-file-readable-p (filename)
|
||||
"Like `file-readable-p' for Tramp files."
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ present for backward compatibility."
|
|||
(let ((a1 (rassq 'ange-ftp-hook-function file-name-handler-alist))
|
||||
(a2 (rassq 'ange-ftp-completion-hook-function file-name-handler-alist)))
|
||||
(setq file-name-handler-alist
|
||||
(delete a1 (delete a2 file-name-handler-alist)))))
|
||||
(seq-difference file-name-handler-alist (list a1 a2)))))
|
||||
|
||||
(with-eval-after-load 'ange-ftp
|
||||
(tramp-disable-ange-ftp))
|
||||
|
|
|
|||
|
|
@ -102,10 +102,7 @@
|
|||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(tramp-fuse-remove-hidden-files
|
||||
(all-completions
|
||||
filename
|
||||
(file-name-all-completions
|
||||
filename (tramp-fuse-local-file-name directory))))))
|
||||
(file-name-all-completions "" (tramp-fuse-local-file-name directory)))))
|
||||
|
||||
;; This function isn't used.
|
||||
(defun tramp-fuse-handle-insert-directory
|
||||
|
|
|
|||
|
|
@ -1479,19 +1479,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
|||
(defun tramp-gvfs-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(unless (string-search "/" filename)
|
||||
(all-completions
|
||||
filename
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(with-tramp-file-property v localname "file-name-all-completions"
|
||||
(let (result)
|
||||
;; Get a list of directories and files.
|
||||
(dolist (item
|
||||
(tramp-gvfs-get-directory-attributes directory)
|
||||
result)
|
||||
(if (string-equal (cdr (assoc "type" item)) "directory")
|
||||
(push (file-name-as-directory (car item)) result)
|
||||
(push (car item) result))))))))))
|
||||
(mapcar #'car (tramp-gvfs-get-directory-attributes directory))))
|
||||
|
||||
(defun tramp-gvfs-handle-file-notify-add-watch (file-name flags _callback)
|
||||
"Like `file-notify-add-watch' for Tramp files."
|
||||
|
|
@ -1545,11 +1533,13 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
|||
(when rest-string
|
||||
(tramp-message proc 10 "Previous string:\n%s" rest-string))
|
||||
(tramp-message proc 6 "%S\n%s" proc string)
|
||||
(setq string (concat rest-string string)
|
||||
;; Fix action names.
|
||||
string (string-replace "attributes changed" "attribute-changed" string)
|
||||
string (string-replace "changes done" "changes-done-hint" string)
|
||||
string (string-replace "renamed to" "moved" string))
|
||||
(setq string
|
||||
(thread-last
|
||||
(concat rest-string string)
|
||||
;; Fix action names.
|
||||
(string-replace "attributes changed" "attribute-changed")
|
||||
(string-replace "changes done" "changes-done-hint")
|
||||
(string-replace "renamed to" "moved")))
|
||||
;; https://bugs.launchpad.net/bugs/1742946
|
||||
(when
|
||||
(string-match-p
|
||||
|
|
|
|||
|
|
@ -1993,48 +1993,39 @@ ID-FORMAT valid values are `string' and `integer'."
|
|||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(when (and (not (string-search "/" filename))
|
||||
(tramp-connectable-p v))
|
||||
(unless (string-search "/" filename)
|
||||
(all-completions
|
||||
filename
|
||||
(with-tramp-file-property v localname "file-name-all-completions"
|
||||
(let (result)
|
||||
;; Get a list of directories and files, including
|
||||
;; reliably tagging the directories with a trailing "/".
|
||||
;; Because I rock. --daniel@danann.net
|
||||
(if (tramp-get-remote-perl v)
|
||||
(tramp-maybe-send-script
|
||||
v tramp-perl-file-name-all-completions
|
||||
"tramp_perl_file_name_all_completions")
|
||||
(tramp-maybe-send-script
|
||||
v tramp-shell-file-name-all-completions
|
||||
"tramp_shell_file_name_all_completions"))
|
||||
(let (result)
|
||||
;; Get a list of directories and files, including reliably
|
||||
;; tagging the directories with a trailing "/".
|
||||
;; Because I rock. --daniel@danann.net
|
||||
(if (tramp-get-remote-perl v)
|
||||
(tramp-maybe-send-script
|
||||
v tramp-perl-file-name-all-completions
|
||||
"tramp_perl_file_name_all_completions")
|
||||
(tramp-maybe-send-script
|
||||
v tramp-shell-file-name-all-completions
|
||||
"tramp_shell_file_name_all_completions"))
|
||||
|
||||
(dolist
|
||||
(elt
|
||||
(tramp-send-command-and-read
|
||||
v (format
|
||||
"%s %s"
|
||||
(if (tramp-get-remote-perl v)
|
||||
"tramp_perl_file_name_all_completions"
|
||||
"tramp_shell_file_name_all_completions")
|
||||
(tramp-shell-quote-argument localname))
|
||||
'noerror)
|
||||
result)
|
||||
;; Don't cache "." and "..".
|
||||
(when (string-match-p
|
||||
directory-files-no-dot-files-regexp
|
||||
(file-name-nondirectory (car elt)))
|
||||
(tramp-set-file-property v (car elt) "file-exists-p" (nth 1 elt))
|
||||
(tramp-set-file-property v (car elt) "file-readable-p" (nth 2 elt))
|
||||
(tramp-set-file-property v (car elt) "file-directory-p" (nth 3 elt))
|
||||
(tramp-set-file-property v (car elt) "file-executable-p" (nth 4 elt)))
|
||||
(dolist
|
||||
(elt
|
||||
(tramp-send-command-and-read
|
||||
v (format
|
||||
"%s %s"
|
||||
(if (tramp-get-remote-perl v)
|
||||
"tramp_perl_file_name_all_completions"
|
||||
"tramp_shell_file_name_all_completions")
|
||||
(tramp-shell-quote-argument localname))
|
||||
'noerror)
|
||||
result)
|
||||
;; Don't cache "." and "..".
|
||||
(when (string-match-p
|
||||
directory-files-no-dot-files-regexp
|
||||
(file-name-nondirectory (car elt)))
|
||||
(tramp-set-file-property v (car elt) "file-exists-p" (nth 1 elt))
|
||||
(tramp-set-file-property v (car elt) "file-readable-p" (nth 2 elt))
|
||||
(tramp-set-file-property v (car elt) "file-directory-p" (nth 3 elt))
|
||||
(tramp-set-file-property v (car elt) "file-executable-p" (nth 4 elt)))
|
||||
|
||||
(push
|
||||
(concat
|
||||
(file-name-nondirectory (car elt)) (and (nth 3 elt) "/"))
|
||||
result))))))))))
|
||||
(push (file-name-nondirectory (car elt)) result))))))
|
||||
|
||||
;; cp, mv and ln
|
||||
|
||||
|
|
@ -2803,7 +2794,7 @@ The method used must be an out-of-band method."
|
|||
(append switches (split-string (tramp-sh--quoting-style-options v))
|
||||
(when dired `(,dired))))
|
||||
(unless dired
|
||||
(setq switches (delete "-N" (delete "--dired" switches)))))
|
||||
(setq switches (seq-difference switches '("-N" "--dired")))))
|
||||
(when wildcard
|
||||
(setq wildcard (tramp-run-real-handler
|
||||
#'file-name-nondirectory (list localname)))
|
||||
|
|
@ -3917,11 +3908,13 @@ Fall back to normal file name handler if no Tramp handler exists."
|
|||
(when rest-string
|
||||
(tramp-message proc 10 "Previous string:\n%s" rest-string))
|
||||
(tramp-message proc 6 "%S\n%s" proc string)
|
||||
(setq string (concat rest-string string)
|
||||
;; Fix action names.
|
||||
string (string-replace "attributes changed" "attribute-changed" string)
|
||||
string (string-replace "changes done" "changes-done-hint" string)
|
||||
string (string-replace "renamed to" "moved" string))
|
||||
(setq string
|
||||
(thread-last
|
||||
(concat rest-string string)
|
||||
;; Fix action names.
|
||||
(string-replace "attributes changed" "attribute-changed")
|
||||
(string-replace "changes done" "changes-done-hint")
|
||||
(string-replace "renamed to" "moved")))
|
||||
|
||||
(catch 'doesnt-work
|
||||
;; https://bugs.launchpad.net/bugs/1742946
|
||||
|
|
@ -5044,7 +5037,7 @@ Goes through the list `tramp-inline-compress-commands'."
|
|||
;; Use plink options.
|
||||
((string-match-p
|
||||
(rx "plink" (? ".exe") eol)
|
||||
(tramp-get-method-parameter vec 'tramp-login-program))
|
||||
(tramp-expand-args vec 'tramp-login-program))
|
||||
(concat
|
||||
(if (eq tramp-use-connection-share 'suppress)
|
||||
"-noshare" "-share")
|
||||
|
|
@ -5405,7 +5398,7 @@ connection if a previous connection has died for some reason."
|
|||
hop 'tramp-connection-timeout
|
||||
tramp-connection-timeout))
|
||||
(command
|
||||
(tramp-get-method-parameter
|
||||
(tramp-expand-args
|
||||
hop 'tramp-login-program))
|
||||
;; We don't create the temporary file. In
|
||||
;; fact, it is just a prefix for the
|
||||
|
|
|
|||
|
|
@ -603,12 +603,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(copy-directory filename newname keep-date 'parents 'copy-contents)
|
||||
|
||||
(tramp-barf-if-file-missing v filename
|
||||
;; `file-local-copy' returns a file name also for a local
|
||||
;; file with `jka-compr-handler', so we cannot trust its
|
||||
;; result as indication for a remote file name.
|
||||
(if-let* ((tmpfile
|
||||
(and (tramp-tramp-file-p filename)
|
||||
(file-local-copy filename))))
|
||||
;; Suppress `jka-compr-handler'.
|
||||
(if-let* ((jka-compr-inhibit t)
|
||||
(tmpfile (file-local-copy filename)))
|
||||
;; Remote filename.
|
||||
(condition-case err
|
||||
(rename-file tmpfile newname ok-if-already-exists)
|
||||
|
|
@ -1068,18 +1065,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(defun tramp-smb-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(all-completions
|
||||
filename
|
||||
(when (file-directory-p directory)
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(with-tramp-file-property v localname "file-name-all-completions"
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(list
|
||||
(if (string-search "d" (nth 1 x))
|
||||
(file-name-as-directory (nth 0 x))
|
||||
(nth 0 x))))
|
||||
(tramp-smb-get-file-entries directory))))))))
|
||||
(mapcar #'car (tramp-smb-get-file-entries directory))))
|
||||
|
||||
(defun tramp-smb-handle-file-system-info (filename)
|
||||
"Like `file-system-info' for Tramp files."
|
||||
|
|
@ -1752,9 +1738,6 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)."
|
|||
(unless share
|
||||
(tramp-set-connection-property v "share-cache" res)))
|
||||
|
||||
;; Add directory itself.
|
||||
(push '("" "drwxrwxrwx" 0 (0 0)) res)
|
||||
|
||||
;; Return entries.
|
||||
(delq nil res)))))
|
||||
|
||||
|
|
@ -2295,9 +2278,6 @@ SHARE will be passed to the call of `tramp-smb-get-localname'."
|
|||
|
||||
;; * Return more comprehensive file permission string.
|
||||
;;
|
||||
;; * Try to remove the inclusion of dummy "" directory. Seems to be at
|
||||
;; several places, especially in `tramp-smb-handle-insert-directory'.
|
||||
;;
|
||||
;; * Keep a separate connection process per share.
|
||||
;;
|
||||
;; * Keep a permanent connection process for `process-file'.
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ arguments to pass to the OPERATION."
|
|||
(setq ret
|
||||
(apply
|
||||
#'tramp-call-process
|
||||
v (tramp-get-method-parameter v 'tramp-login-program)
|
||||
v (tramp-expand-args v 'tramp-login-program)
|
||||
nil outbuf display
|
||||
(tramp-expand-args
|
||||
v 'tramp-login-args nil
|
||||
|
|
|
|||
|
|
@ -498,24 +498,16 @@ the result will be a local, non-Tramp, file name."
|
|||
(defun tramp-sudoedit-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(all-completions
|
||||
filename
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(with-tramp-file-property v localname "file-name-all-completions"
|
||||
(tramp-sudoedit-send-command
|
||||
v "ls" "-a1" "--quoting-style=literal" "--show-control-chars"
|
||||
(if (tramp-string-empty-or-nil-p localname)
|
||||
"" (file-name-unquote localname)))
|
||||
(mapcar
|
||||
(lambda (f)
|
||||
(if (ignore-errors (file-directory-p (expand-file-name f directory)))
|
||||
(file-name-as-directory f)
|
||||
f))
|
||||
(mapcar
|
||||
(lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
|
||||
(split-string
|
||||
(tramp-get-buffer-string (tramp-get-connection-buffer v))
|
||||
"\n" 'omit))))))))
|
||||
(with-parsed-tramp-file-name (expand-file-name directory) nil
|
||||
(tramp-sudoedit-send-command
|
||||
v "ls" "-a1" "--quoting-style=literal" "--show-control-chars"
|
||||
(if (tramp-string-empty-or-nil-p localname)
|
||||
"" (file-name-unquote localname)))
|
||||
(mapcar
|
||||
(lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
|
||||
(split-string
|
||||
(tramp-get-buffer-string (tramp-get-connection-buffer v))
|
||||
"\n" 'omit)))))
|
||||
|
||||
(defun tramp-sudoedit-handle-file-readable-p (filename)
|
||||
"Like `file-readable-p' for Tramp files."
|
||||
|
|
|
|||
|
|
@ -2002,12 +2002,11 @@ expected to be a string, which will be used."
|
|||
"Construct a Tramp hop name from VEC."
|
||||
(concat
|
||||
(tramp-file-name-hop vec)
|
||||
(replace-regexp-in-string
|
||||
tramp-prefix-regexp ""
|
||||
(replace-regexp-in-string
|
||||
(rx (regexp tramp-postfix-host-regexp) eos)
|
||||
tramp-postfix-hop-format
|
||||
(tramp-make-tramp-file-name (tramp-file-name-unify vec))))))
|
||||
(thread-last
|
||||
(replace-regexp-in-string
|
||||
(rx (regexp tramp-postfix-host-regexp) eos) tramp-postfix-hop-format
|
||||
(tramp-make-tramp-file-name (tramp-file-name-unify vec)))
|
||||
(replace-regexp-in-string tramp-prefix-regexp ""))))
|
||||
|
||||
(defun tramp-completion-make-tramp-file-name (method user host localname)
|
||||
"Construct a Tramp file name from METHOD, USER, HOST and LOCALNAME.
|
||||
|
|
@ -2957,7 +2956,7 @@ not in completion mode."
|
|||
(or (and (cond
|
||||
;; Completion styles like `flex' and `substring' check for
|
||||
;; the file name "/". This does exist.
|
||||
((string-equal filename "/"))
|
||||
((string-equal filename tramp-prefix-format))
|
||||
;; Is it a valid method?
|
||||
((and (not (string-empty-p tramp-postfix-method-format))
|
||||
(string-match
|
||||
|
|
@ -3001,30 +3000,59 @@ not in completion mode."
|
|||
|
||||
(tramp-run-real-handler #'file-exists-p (list filename))))
|
||||
|
||||
(defvar tramp-fnac-add-trailing-slash t
|
||||
"Whether `file-name-all-completions' shall add a trailing slash.
|
||||
This is not desired, if that function is used in `directory-files', or
|
||||
in `tramp-completion-handle-file-name-all-completions'.")
|
||||
|
||||
(defmacro tramp-skeleton-file-name-all-completions
|
||||
(filename directory &rest body)
|
||||
"Skeleton for `tramp-*-handle-filename-all-completions'.
|
||||
BODY is the backend specific code."
|
||||
(declare (indent 2) (debug t))
|
||||
`(ignore-error file-missing
|
||||
(seq-uniq (delq nil (delete ""
|
||||
(let* ((case-fold-search read-file-name-completion-ignore-case)
|
||||
(result (progn ,@body)))
|
||||
;; Some storage systems do not return "." and "..".
|
||||
(when (tramp-tramp-file-p ,directory)
|
||||
(dolist (elt '(".." "."))
|
||||
(when (string-prefix-p ,filename elt)
|
||||
(setq result (cons (concat elt "/") result)))))
|
||||
(if (consp completion-regexp-list)
|
||||
;; Discriminate over `completion-regexp-list'.
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(when (stringp x)
|
||||
(catch 'match
|
||||
(dolist (elt completion-regexp-list x)
|
||||
(unless (string-match-p elt x) (throw 'match nil))))))
|
||||
result)
|
||||
result)))))))
|
||||
(all-completions
|
||||
,filename
|
||||
(when (file-directory-p ,directory)
|
||||
(seq-uniq (delq nil
|
||||
(let* ((case-fold-search read-file-name-completion-ignore-case)
|
||||
(result
|
||||
(if (tramp-tramp-file-p ,directory)
|
||||
(with-parsed-tramp-file-name
|
||||
(expand-file-name ,directory) nil
|
||||
(when (and (not (string-search "/" ,filename))
|
||||
(tramp-connectable-p v))
|
||||
(with-tramp-file-property
|
||||
v localname
|
||||
(format
|
||||
"file-name-all-completions-%s"
|
||||
tramp-fnac-add-trailing-slash)
|
||||
;; Mark symlinked directories. Other
|
||||
;; directories are already marked.
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(let ((f (file-name-concat ,directory x)))
|
||||
(if (and tramp-fnac-add-trailing-slash
|
||||
(not (string-suffix-p "/" x))
|
||||
(file-directory-p
|
||||
(if (file-symlink-p f)
|
||||
(file-truename f) f)))
|
||||
(concat x "/") x)))
|
||||
;; Some storage systems do not return "." and "..".
|
||||
(seq-union
|
||||
(seq-difference (progn ,@body) '("." ".."))
|
||||
'("./" "../"))))))
|
||||
,@body)))
|
||||
;; Discriminate over `completion-regexp-list'.
|
||||
(if (consp completion-regexp-list)
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(when (stringp x)
|
||||
(catch 'match
|
||||
(dolist (elt completion-regexp-list x)
|
||||
(unless (string-match-p elt x) (throw 'match nil))))))
|
||||
result)
|
||||
result))))))))
|
||||
|
||||
(defvar tramp--last-hop-directory nil
|
||||
"Tracks the directory from which to run login programs.")
|
||||
|
|
@ -3035,72 +3063,74 @@ BODY is the backend specific code."
|
|||
;; completions.
|
||||
(defun tramp-completion-handle-file-name-all-completions (filename directory)
|
||||
"Like `file-name-all-completions' for partial Tramp files."
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(let ((fullname
|
||||
(tramp-drop-volume-letter (expand-file-name filename directory)))
|
||||
(directory (tramp-drop-volume-letter directory))
|
||||
tramp--last-hop-directory hop result result1)
|
||||
(let (tramp-fnac-add-trailing-slash)
|
||||
(tramp-skeleton-file-name-all-completions filename directory
|
||||
(let ((fullname
|
||||
(tramp-drop-volume-letter (expand-file-name filename directory)))
|
||||
(directory (tramp-drop-volume-letter directory))
|
||||
tramp--last-hop-directory hop result result1)
|
||||
|
||||
;; Suppress hop from completion.
|
||||
(when (string-match
|
||||
(rx
|
||||
(regexp tramp-prefix-regexp)
|
||||
(group (+ (regexp tramp-remote-file-name-spec-regexp)
|
||||
(regexp tramp-postfix-hop-regexp))))
|
||||
fullname)
|
||||
(setq hop (match-string 1 fullname)
|
||||
fullname (replace-match "" nil nil fullname 1)
|
||||
tramp--last-hop-directory
|
||||
(tramp-make-tramp-file-name (tramp-dissect-hop-name hop))))
|
||||
;; Suppress hop from completion.
|
||||
(when (string-match
|
||||
(rx
|
||||
(regexp tramp-prefix-regexp)
|
||||
(group (+ (regexp tramp-remote-file-name-spec-regexp)
|
||||
(regexp tramp-postfix-hop-regexp))))
|
||||
fullname)
|
||||
(setq hop (match-string 1 fullname)
|
||||
fullname (replace-match "" nil nil fullname 1)
|
||||
tramp--last-hop-directory
|
||||
(tramp-make-tramp-file-name (tramp-dissect-hop-name hop))))
|
||||
|
||||
(let (tramp-default-user tramp-default-user-alist
|
||||
tramp-default-host tramp-default-host-alist)
|
||||
(let (tramp-default-user tramp-default-user-alist
|
||||
tramp-default-host tramp-default-host-alist)
|
||||
|
||||
;; Possible completion structures.
|
||||
(dolist (elt (tramp-completion-dissect-file-name fullname))
|
||||
(let* ((method (tramp-file-name-method elt))
|
||||
(user (tramp-file-name-user elt))
|
||||
(host (tramp-file-name-host elt))
|
||||
(localname (tramp-file-name-localname elt))
|
||||
(m (tramp-find-method method user host))
|
||||
all-user-hosts)
|
||||
;; Possible completion structures.
|
||||
(dolist (elt (tramp-completion-dissect-file-name fullname))
|
||||
(let* ((method (tramp-file-name-method elt))
|
||||
(user (tramp-file-name-user elt))
|
||||
(host (tramp-file-name-host elt))
|
||||
(localname (tramp-file-name-localname elt))
|
||||
(m (tramp-find-method method user host))
|
||||
all-user-hosts)
|
||||
|
||||
(unless localname ;; Nothing to complete.
|
||||
(if (or user host)
|
||||
;; Method dependent user / host combinations.
|
||||
(progn
|
||||
(mapc
|
||||
(lambda (x)
|
||||
(setq all-user-hosts
|
||||
(append all-user-hosts
|
||||
(funcall (nth 0 x) (nth 1 x)))))
|
||||
(tramp-get-completion-function m))
|
||||
(unless localname ;; Nothing to complete.
|
||||
(if (or user host)
|
||||
;; Method dependent user / host combinations.
|
||||
(progn
|
||||
(mapc
|
||||
(lambda (x)
|
||||
(setq all-user-hosts
|
||||
(append all-user-hosts
|
||||
(funcall (nth 0 x) (nth 1 x)))))
|
||||
(tramp-get-completion-function m))
|
||||
|
||||
(setq result
|
||||
(append result
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(tramp-get-completion-user-host
|
||||
method user host (nth 0 x) (nth 1 x)))
|
||||
all-user-hosts))))
|
||||
(setq result
|
||||
(append result
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(tramp-get-completion-user-host
|
||||
method user host (nth 0 x) (nth 1 x)))
|
||||
all-user-hosts))))
|
||||
|
||||
;; Possible methods.
|
||||
(setq result
|
||||
(append result (tramp-get-completion-methods m hop)))))))
|
||||
;; Possible methods.
|
||||
(setq result
|
||||
(append result (tramp-get-completion-methods m hop)))))))
|
||||
|
||||
;; Add hop.
|
||||
(dolist (elt result)
|
||||
(when elt
|
||||
(setq elt (replace-regexp-in-string
|
||||
tramp-prefix-regexp (concat tramp-prefix-format hop) elt))
|
||||
(push (substring elt (length directory)) result1)))
|
||||
;; Add hop.
|
||||
(dolist (elt result)
|
||||
(when elt
|
||||
(setq elt (replace-regexp-in-string
|
||||
tramp-prefix-regexp
|
||||
(concat tramp-prefix-format hop) elt))
|
||||
(push (substring elt (length directory)) result1)))
|
||||
|
||||
;; Complete local parts.
|
||||
(append
|
||||
result1
|
||||
(ignore-errors
|
||||
(tramp-run-real-handler
|
||||
#'file-name-all-completions (list filename directory))))))))
|
||||
;; Complete local parts.
|
||||
(append
|
||||
result1
|
||||
(ignore-errors
|
||||
(tramp-run-real-handler
|
||||
#'file-name-all-completions (list filename directory)))))))))
|
||||
|
||||
;; Method, host name and user name completion for a file.
|
||||
(defun tramp-completion-handle-file-name-completion
|
||||
|
|
@ -3659,9 +3689,10 @@ BODY is the backend specific code."
|
|||
(signal 'error nil)
|
||||
(setf ,directory
|
||||
(file-name-as-directory (expand-file-name ,directory)))
|
||||
(let ((temp
|
||||
(with-tramp-file-property v localname "directory-files" ,@body))
|
||||
result item)
|
||||
(let* (tramp-fnac-add-trailing-slash
|
||||
(temp
|
||||
(with-tramp-file-property v localname "directory-files" ,@body))
|
||||
result item)
|
||||
(while temp
|
||||
(setq item (directory-file-name (pop temp)))
|
||||
(when (or (null ,match) (string-match-p ,match item))
|
||||
|
|
@ -4496,8 +4527,8 @@ Let-bind it when necessary.")
|
|||
;; "." and ".." are never interesting as completions, and are
|
||||
;; actually in the way in a directory with only one file. See
|
||||
;; file_name_completion() in dired.c.
|
||||
(when (and (consp fnac) (length= (delete "./" (delete "../" fnac)) 1))
|
||||
(setq fnac (delete "./" (delete "../" fnac))))
|
||||
(when (and (consp fnac) (length= (seq-difference fnac '("./" "../")) 1))
|
||||
(setq fnac (seq-difference fnac '("./" "../"))))
|
||||
(or
|
||||
(try-completion
|
||||
filename fnac
|
||||
|
|
@ -5294,7 +5325,7 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
|
|||
(defvar tramp-extra-expand-args nil
|
||||
"Method specific arguments.")
|
||||
|
||||
(defun tramp-expand-args (vec parameter default &rest spec-list)
|
||||
(defun tramp-expand-args (vec parameter &optional default &rest spec-list)
|
||||
"Expand login arguments as given by PARAMETER in `tramp-methods'.
|
||||
PARAMETER is a symbol like `tramp-login-args', denoting a list of
|
||||
list of strings from `tramp-methods', containing %-sequences for
|
||||
|
|
@ -5317,12 +5348,15 @@ a connection-local variable."
|
|||
(setq spec-list (cddr spec-list)))
|
||||
(setq spec (apply #'format-spec-make extra-spec-list))
|
||||
;; Expand format spec.
|
||||
(flatten-tree
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(setq x (mapcar (lambda (y) (tramp-format-spec y spec)) x))
|
||||
(unless (member "" x) x))
|
||||
args))))
|
||||
(cond
|
||||
((consp args)
|
||||
(flatten-tree
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(setq x (mapcar (lambda (y) (tramp-format-spec y spec)) x))
|
||||
(unless (member "" x) x))
|
||||
args)))
|
||||
(args (tramp-format-spec args spec)))))
|
||||
|
||||
(defun tramp-post-process-creation (proc vec)
|
||||
"Apply actions after creation of process PROC."
|
||||
|
|
@ -5444,8 +5478,7 @@ processes."
|
|||
(tramp-get-method-parameter v 'tramp-direct-async)
|
||||
`(,(string-join command " ")))
|
||||
command))
|
||||
(login-program
|
||||
(tramp-get-method-parameter v 'tramp-login-program))
|
||||
(login-program (tramp-expand-args v 'tramp-login-program))
|
||||
;; We don't create the temporary file. In fact, it is just
|
||||
;; a prefix for the ControlPath option of ssh; the real
|
||||
;; temporary file has another name, and it is created and
|
||||
|
|
@ -5487,7 +5520,7 @@ processes."
|
|||
v 'tramp-login-args nil
|
||||
?h (or host "") ?u (or user "") ?p (or port "")
|
||||
?c (format-spec (or options "") (format-spec-make ?t tmpfile))
|
||||
?d (or device "") ?a (or pta "") ?l ""))))
|
||||
?w "" ?d (or device "") ?a (or pta "") ?l ""))))
|
||||
;; Suppress `internal-default-process-sentinel', which is set
|
||||
;; when :sentinel is nil. (Bug#71049)
|
||||
p (make-process
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ Linum mode is a buffer-local minor mode."
|
|||
;; Note that nowadays, this actually doesn't show line
|
||||
;; numbers in client frames at all, because we visit the
|
||||
;; file before creating the client frame. See bug#35726.
|
||||
;; Use `frame-initial-p'?
|
||||
(and (daemonp) (eq (selected-frame) terminal-frame)))
|
||||
(linum-mode 1)))
|
||||
|
||||
|
|
|
|||
|
|
@ -326,10 +326,10 @@ non-nil and point is located on the heading line.")
|
|||
(defcustom outline-minor-mode-use-buttons nil
|
||||
"Whether to display clickable buttons on the headings.
|
||||
These buttons can be used to hide and show the body under the heading.
|
||||
When the value is `insert', additional placeholders for buttons are
|
||||
When the value is \\+`insert', additional placeholders for buttons are
|
||||
inserted to the buffer, so buttons are not only clickable,
|
||||
but also typing `RET' on them can hide and show the body.
|
||||
Using the value `insert' is not recommended in editable
|
||||
Using the value \\+`insert' is not recommended in editable
|
||||
buffers because it modifies them.
|
||||
When the value is `in-margins', then clickable buttons are
|
||||
displayed in the margins before the headings.
|
||||
|
|
@ -513,7 +513,7 @@ font-lock faces defined by the major mode. Thus, a non-nil value will
|
|||
work well only when there's no such conflict.
|
||||
If the value is t, use outline faces only if there are no major mode's
|
||||
font-lock faces on headings. When `override', completely overwrite major
|
||||
mode's font-lock faces with outline faces. When `append', try to append
|
||||
mode's font-lock faces with outline faces. When \\+`append', try to append
|
||||
outline font-lock faces to those of major mode."
|
||||
:type '(choice (const :tag "Do not use outline font-lock highlighting" nil)
|
||||
(const :tag "Overwrite major mode font-lock faces" override)
|
||||
|
|
|
|||
|
|
@ -434,9 +434,10 @@ It is the default value of `show-paren-data-function'."
|
|||
(overlay-put show-paren--context-overlay 'priority
|
||||
show-paren-priority)
|
||||
(overlay-put show-paren--context-overlay
|
||||
'face `(:box
|
||||
( :line-width (1 . -1)
|
||||
:color ,(face-attribute 'shadow :foreground))))
|
||||
'face `( :inherit default
|
||||
:box
|
||||
( :line-width (1 . -1)
|
||||
:color ,(face-attribute 'shadow :foreground))))
|
||||
(add-hook 'post-command-hook #'show-paren--delete-context-overlay
|
||||
nil 'local))
|
||||
|
||||
|
|
|
|||
|
|
@ -1431,7 +1431,7 @@ COMMAND Name of the program for printing a text file. On MS-DOS and
|
|||
specially, using NAME as the destination for output; any other
|
||||
program is treated like `lpr' except that an explicit filename
|
||||
is given as the last argument.
|
||||
If COMMAND is nil, it's used the default printing program:
|
||||
If COMMAND is nil, it stands for the default printing program:
|
||||
`print' for Windows system, `lp' for lp system and `lpr' for
|
||||
all other systems. See also `pr-path-alist'.
|
||||
Examples:
|
||||
|
|
@ -1506,7 +1506,10 @@ Useful links:
|
|||
:type '(repeat
|
||||
(list :tag "Text Printer"
|
||||
(symbol :tag "Printer Symbol Name")
|
||||
(string :tag "Printer Command")
|
||||
(choice :menu-tag "Printer Command"
|
||||
:tag "Printer Command"
|
||||
(const :tag "Default print command" nil)
|
||||
(string :tag "Explicit print command"))
|
||||
(repeat :tag "Printer Switches"
|
||||
(sexp :tag "Switch" :value ""))
|
||||
(choice :menu-tag "Printer Name"
|
||||
|
|
@ -1577,7 +1580,7 @@ COMMAND Name of the program for printing a PostScript file. On MS-DOS
|
|||
specially, using NAME as the destination for output; any other
|
||||
program is treated like `lpr' except that an explicit filename
|
||||
is given as the last argument.
|
||||
If COMMAND is nil, it's used the default printing program:
|
||||
If COMMAND is nil, it stands for the default printing program:
|
||||
`print' for Windows system, `lp' for lp system and `lpr' for
|
||||
all other systems. See also `pr-path-alist'.
|
||||
Examples:
|
||||
|
|
@ -1756,7 +1759,10 @@ Useful links:
|
|||
(list
|
||||
:tag "PostScript Printer"
|
||||
(symbol :tag "Printer Symbol Name")
|
||||
(string :tag "Printer Command")
|
||||
(choice :menu-tag "Printer Command"
|
||||
:tag "Printer Command"
|
||||
(const :tag "Default print command" nil)
|
||||
(string :tag "Explicit print command"))
|
||||
(repeat :tag "Printer Switches"
|
||||
(sexp :tag "Switch" :value ""))
|
||||
(choice :menu-tag "Printer Name Switch"
|
||||
|
|
|
|||
|
|
@ -1567,6 +1567,7 @@ recommended to enable `electric-pair-mode' with this mode."
|
|||
(funcall c-ts-mode-indent-style)
|
||||
(c-ts-mode--simple-indent-rules
|
||||
'cpp c-ts-mode-indent-style)))
|
||||
(setq-local editorconfig-indent-size-vars '(c-ts-indent-offset))
|
||||
|
||||
;; Font-lock.
|
||||
(setq-local treesit-font-lock-settings
|
||||
|
|
|
|||
|
|
@ -991,6 +991,8 @@ You might also use mode hooks to specify it in certain modes, like this:
|
|||
(file-name-sans-extension buffer-file-name))))))))
|
||||
|
||||
It's often useful to leave a space at the end of the value."
|
||||
:group 'compilation
|
||||
:initialize #'custom-initialize-delay
|
||||
:type 'string)
|
||||
;;;###autoload(put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (if (boundp 'compilation-read-command) compilation-read-command t))))
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
;; Copyright (C) 2018-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Version: 1.21
|
||||
;; Version: 1.23
|
||||
;; Author: João Távora <joaotavora@gmail.com>
|
||||
;; Maintainer: João Távora <joaotavora@gmail.com>
|
||||
;; URL: https://github.com/joaotavora/eglot
|
||||
;; Keywords: convenience, languages
|
||||
;; Package-Requires: ((emacs "26.3") (eldoc "1.14.0") (external-completion "0.1") (flymake "1.4.2") (jsonrpc "1.0.26") (project "0.11.2") (seq "2.23") (xref "1.6.2"))
|
||||
;; Package-Requires: ((emacs "26.3") (eldoc "1.16.0") (external-completion "0.1") (flymake "1.4.5") (jsonrpc "1.0.28") (project "0.11.2") (seq "2.23") (xref "1.7.0"))
|
||||
|
||||
;; This is a GNU ELPA :core package. Avoid adding functionality
|
||||
;; that is not available in the version of Emacs recorded above or any
|
||||
|
|
@ -2710,10 +2710,11 @@ still unanswered LSP requests to the server\n"))))
|
|||
|
||||
(defconst eglot-mode-line-progress
|
||||
'(:eval
|
||||
(when-let ((server (eglot-current-server)))
|
||||
(when-let ((s (eglot-current-server)))
|
||||
(cl-loop
|
||||
for pr hash-values of (eglot--progress-reporters server)
|
||||
when (eq (car pr) 'eglot--mode-line-reporter)
|
||||
for pr in (cl-delete 'eglot--mode-line-reporter
|
||||
(hash-table-values (eglot--progress-reporters s))
|
||||
:key #'car :test-not #'eq)
|
||||
for v = (nth 4 pr)
|
||||
when v sum 1 into n and sum v into acc
|
||||
collect (format "(%s) %s %s" (nth 1 pr) (nth 2 pr) (nth 3 pr))
|
||||
|
|
@ -4092,7 +4093,7 @@ for which LSP on-type-formatting should be requested."
|
|||
parameter
|
||||
;; ...perhaps highlight it in the formals list
|
||||
(when (eq i active-param)
|
||||
(save-excursion ;; FIXME: Sink into the `if' or hoist out of loop?
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(pcase-let
|
||||
((`(,beg ,end)
|
||||
|
|
@ -4100,8 +4101,7 @@ for which LSP on-type-formatting should be requested."
|
|||
(let ((case-fold-search nil))
|
||||
(and (search-forward parlabel (line-end-position) t)
|
||||
(list (match-beginning 0) (match-end 0))))
|
||||
(list (+ (point-min) (aref parlabel 0))
|
||||
(+ (point-min) (aref parlabel 1))))))
|
||||
(list (1+ (aref parlabel 0)) (1+ (aref parlabel 1))))))
|
||||
(if (and beg end)
|
||||
(add-face-text-property
|
||||
beg end
|
||||
|
|
|
|||
|
|
@ -1330,6 +1330,8 @@ Interactively, with a prefix arg, FORCE is t."
|
|||
(buffer (current-buffer)))
|
||||
(cl-labels
|
||||
((visible-buffer-window ()
|
||||
;; This can use `frame-initial-p' once
|
||||
;; we can assume Emacs 31 or later.
|
||||
(and (or (not (daemonp))
|
||||
(not (eq (selected-frame) terminal-frame)))
|
||||
(get-buffer-window (current-buffer))))
|
||||
|
|
|
|||
|
|
@ -1089,11 +1089,15 @@ list is empty)."
|
|||
match)
|
||||
(while (setq match (text-property-search-forward 'compilation-annotation))
|
||||
(add-text-properties (prop-match-beginning match) (prop-match-end match)
|
||||
'(read-only t)))
|
||||
'(read-only t front-sticky t)))
|
||||
(goto-char (point-min))
|
||||
(while (setq match (text-property-search-forward 'compilation-message))
|
||||
(add-text-properties (prop-match-beginning match) (prop-match-end match)
|
||||
'(read-only t occur-prefix t))
|
||||
'( read-only t occur-prefix t
|
||||
;; Allow insertion of text right
|
||||
;; after prefix, but not before.
|
||||
front-sticky t
|
||||
rear-nonsticky t))
|
||||
(let ((loc (compilation--message->loc (prop-match-value match)))
|
||||
m)
|
||||
;; Update the markers if necessary.
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
(require 'cl-lib)
|
||||
(require 'ring)
|
||||
(require 'project)
|
||||
(require 'text-property-search)
|
||||
|
||||
(eval-and-compile
|
||||
(when (version< emacs-version "28.0.60")
|
||||
|
|
@ -628,7 +629,7 @@ If SELECT is non-nil, select the target window."
|
|||
(run-hooks 'xref-after-jump-hook)))
|
||||
|
||||
|
||||
;;; XREF buffer (part of the UI)
|
||||
;;; Xref buffer (part of the UI)
|
||||
|
||||
;; The xref buffer is used to display a set of xrefs.
|
||||
(defconst xref-buffer-name "*xref*"
|
||||
|
|
@ -1004,12 +1005,13 @@ point."
|
|||
(define-key map (kbd ".") #'xref-next-line)
|
||||
(define-key map (kbd ",") #'xref-prev-line)
|
||||
(define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack)
|
||||
(define-key map (kbd "e") #'xref-change-to-xref-edit-mode)
|
||||
map))
|
||||
|
||||
(declare-function outline-search-text-property "outline"
|
||||
(property &optional value bound move backward looking-at))
|
||||
|
||||
(define-derived-mode xref--xref-buffer-mode special-mode "XREF"
|
||||
(define-derived-mode xref--xref-buffer-mode special-mode "Xref"
|
||||
"Mode for displaying cross-references."
|
||||
(setq buffer-read-only t)
|
||||
(setq next-error-function #'xref--next-error-function)
|
||||
|
|
@ -1039,7 +1041,7 @@ point."
|
|||
|
||||
(define-derived-mode xref--transient-buffer-mode
|
||||
xref--xref-buffer-mode
|
||||
"XREF Transient.")
|
||||
"Xref Transient")
|
||||
|
||||
(defun xref--imenu-prev-index-position ()
|
||||
"Move point to previous line in `xref' buffer.
|
||||
|
|
@ -1470,6 +1472,106 @@ between them by typing in the minibuffer with completion."
|
|||
(define-obsolete-function-alias
|
||||
'xref--show-defs-minibuffer #'xref-show-definitions-completing-read "28.1")
|
||||
|
||||
|
||||
(defun xref-edit--prepare-buffer ()
|
||||
"Mark relevant regions read-only, and add relevant occur text-properties."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((inhibit-read-only t)
|
||||
match)
|
||||
(while (setq match (text-property-search-forward 'xref-group))
|
||||
(add-text-properties (prop-match-beginning match) (prop-match-end match)
|
||||
'( read-only t
|
||||
front-sticky t)))
|
||||
(goto-char (point-min))
|
||||
(while (setq match (text-property-search-forward 'xref-item))
|
||||
(let ((line-number-end (save-excursion
|
||||
(forward-line 0)
|
||||
(and (looking-at " *[0-9]+:")
|
||||
(match-end 0)))))
|
||||
(when line-number-end
|
||||
(add-text-properties (prop-match-beginning match) line-number-end
|
||||
'( read-only t
|
||||
occur-prefix t
|
||||
;; Allow insertion of text right
|
||||
;; after prefix, but not before.
|
||||
front-sticky t
|
||||
rear-nonsticky t))))))))
|
||||
|
||||
(defvar xref-edit-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-c C-c") #'xref-edit-save-changes)
|
||||
(define-key map (kbd "RET") #'xref-goto-xref)
|
||||
(define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack)
|
||||
(define-key map (kbd "C-o") #'xref-show-location-at-point)
|
||||
map)
|
||||
"Keymap for `xref-edit-mode'.")
|
||||
|
||||
(defvar xref-edit-mode-hook nil
|
||||
"Hooks run when changing to Xref-Edit mode.")
|
||||
|
||||
(defun xref-edit-mode ()
|
||||
"Major mode for editing *xref* buffers.
|
||||
In this mode, changes to the *xref* buffer are applied to the
|
||||
originating files.
|
||||
\\<xref-edit-mode-map>
|
||||
Type \\[xref-edit-save-changes] to exit Xref-Edit mode, return to Xref
|
||||
mode.
|
||||
|
||||
The only editable texts in an Xref-Edit buffer are the match results."
|
||||
(interactive)
|
||||
(error "This mode can be enabled only by `xref-change-to-xref-edit-mode'"))
|
||||
(put 'xref-edit-mode 'mode-class 'special)
|
||||
|
||||
(defun xref-change-to-xref-edit-mode ()
|
||||
"Switch to `xref-edit-mode' to edit *xref* buffer."
|
||||
(interactive)
|
||||
(unless (derived-mode-p 'xref--xref-buffer-mode)
|
||||
(error "Not an Xref buffer"))
|
||||
(use-local-map xref-edit-mode-map)
|
||||
(xref-edit--prepare-buffer)
|
||||
(setq buffer-read-only nil)
|
||||
(setq major-mode 'xref-edit-mode)
|
||||
(setq mode-name "Xref-Edit")
|
||||
(buffer-enable-undo)
|
||||
(set-buffer-modified-p nil)
|
||||
(setq buffer-undo-list nil)
|
||||
(add-hook 'before-change-functions #'xref-edit--before-change-function nil t)
|
||||
(add-hook 'after-change-functions #'occur-after-change-function nil t)
|
||||
(run-mode-hooks 'xref-edit-mode-hook)
|
||||
(message (substitute-command-keys
|
||||
"Editing: Type \\[xref-edit-save-changes] to return to Xref mode")))
|
||||
|
||||
(defun xref-edit-save-changes ()
|
||||
"Switch back to Xref mode."
|
||||
(interactive)
|
||||
(unless (derived-mode-p 'xref-edit-mode)
|
||||
(error "Not a Xref-Edit buffer"))
|
||||
(remove-hook 'before-change-functions #'xref-edit--before-change-function t)
|
||||
(remove-hook 'after-change-functions #'occur-after-change-function t)
|
||||
(use-local-map xref--xref-buffer-mode-map)
|
||||
(setq buffer-read-only t)
|
||||
(setq major-mode 'xref--xref-buffer-mode)
|
||||
(setq mode-name "Xref")
|
||||
(force-mode-line-update)
|
||||
(buffer-disable-undo)
|
||||
(setq buffer-undo-list t)
|
||||
(let ((inhibit-read-only t))
|
||||
(remove-text-properties (point-min) (point-max)
|
||||
'(occur-target nil occur-prefix nil)))
|
||||
(message "Switching to Xref mode"))
|
||||
|
||||
(defun xref-edit--before-change-function (_beg _end)
|
||||
(when (and (not (get-text-property (pos-bol) 'occur-target))
|
||||
(get-text-property (pos-bol) 'occur-prefix))
|
||||
(let ((m (xref-location-marker (xref-item-location
|
||||
(get-text-property (pos-bol) 'xref-item))))
|
||||
(inhibit-read-only t)
|
||||
(inhibit-modification-hooks t)
|
||||
(buffer-undo-list t))
|
||||
(add-text-properties (pos-bol) (pos-eol)
|
||||
`(occur-target ((,m . ,m)))))))
|
||||
|
||||
|
||||
(defcustom xref-show-xrefs-function 'xref--show-xref-buffer
|
||||
"Function to display a list of search results.
|
||||
|
|
|
|||
|
|
@ -706,6 +706,7 @@ the `server-process' variable."
|
|||
;; when we can't get user input, which may happen when
|
||||
;; doing emacsclient --eval "(kill-emacs)" in daemon mode.
|
||||
(cond
|
||||
;; Use `frame-initial-p'?
|
||||
((and (daemonp)
|
||||
(null (cdr (frame-list)))
|
||||
(eq (selected-frame) terminal-frame))
|
||||
|
|
@ -1429,6 +1430,7 @@ The following commands are accepted by the client:
|
|||
(or (eq use-current-frame 'always)
|
||||
;; We can't use the Emacs daemon's
|
||||
;; terminal frame.
|
||||
;; Use `frame-initial-p'?
|
||||
(not (and (daemonp)
|
||||
(null (cdr (frame-list)))
|
||||
(eq (selected-frame)
|
||||
|
|
@ -1453,6 +1455,7 @@ The following commands are accepted by the client:
|
|||
;; If there won't be a current frame to use, fall
|
||||
;; back to trying to create a new one.
|
||||
((and use-current-frame
|
||||
;; Use `frame-initial-p'?
|
||||
(daemonp)
|
||||
(null (cdr (frame-list)))
|
||||
(eq (selected-frame) terminal-frame)
|
||||
|
|
|
|||
17
lisp/subr.el
17
lisp/subr.el
|
|
@ -160,6 +160,10 @@ of previous VARs.
|
|||
(push `(set-default ',(pop args) ,(pop args)) exps))
|
||||
`(progn . ,(nreverse exps))))
|
||||
|
||||
(defun set-local (variable value)
|
||||
"Make VARIABLE buffer local and set it to VALUE."
|
||||
(set (make-local-variable variable) value))
|
||||
|
||||
(defmacro setq-local (&rest pairs)
|
||||
"Make each VARIABLE local to current buffer and set it to corresponding VALUE.
|
||||
|
||||
|
|
@ -181,7 +185,7 @@ In some corner cases you may need to resort to
|
|||
\(fn [VARIABLE VALUE]...)"
|
||||
(declare (debug setq))
|
||||
(unless (evenp (length pairs))
|
||||
(error "PAIRS must have an even number of variable/value members"))
|
||||
(signal 'wrong-number-of-arguments (list 'setq-local (length pairs))))
|
||||
(let ((expr nil))
|
||||
(while pairs
|
||||
(unless (symbolp (car pairs))
|
||||
|
|
@ -229,7 +233,7 @@ in order to restore the state of the local variables set via this macro.
|
|||
\(fn [VARIABLE VALUE]...)"
|
||||
(declare (debug setq))
|
||||
(unless (evenp (length pairs))
|
||||
(error "PAIRS must have an even number of variable/value members"))
|
||||
(signal 'wrong-number-of-arguments (list 'buffer-local-set-state (length pairs))))
|
||||
(let ((vars nil)
|
||||
(tmp pairs))
|
||||
(while tmp (push (car tmp) vars) (setq tmp (cddr tmp)))
|
||||
|
|
@ -1226,8 +1230,13 @@ with
|
|||
(member-if (lambda (x) (foo (bar x))) items)"
|
||||
(declare (compiler-macro
|
||||
(lambda (_)
|
||||
(let ((x (make-symbol "x")))
|
||||
`(drop-while (lambda (,x) (not (funcall ,pred ,x))) ,list)))))
|
||||
(let* ((x (make-symbol "x"))
|
||||
(f (and (not (internal--effect-free-fun-arg-p pred))
|
||||
(make-symbol "f")))
|
||||
(form `(drop-while (lambda (,x)
|
||||
(not (funcall ,(or f pred) ,x)))
|
||||
,list)))
|
||||
(if f `(let ((,f ,pred)) ,form) form)))))
|
||||
(drop-while (lambda (x) (not (funcall pred x))) list))
|
||||
|
||||
;; This is good to have for improved readability in certain uses, but
|
||||
|
|
|
|||
|
|
@ -292,6 +292,7 @@ a list of frames to update."
|
|||
(and (eq auto-resize-tab-bars 'grow-only)
|
||||
(> (frame-parameter frame 'tab-bar-lines) 1))
|
||||
;; Don't enable tab-bar in daemon's initial frame.
|
||||
;; Use `frame-initial-p'?
|
||||
(and (daemonp) (eq frame terminal-frame)))
|
||||
(set-frame-parameter frame 'tab-bar-lines
|
||||
(tab-bar--tab-bar-lines-for-frame frame)))))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
;; Copyright (C) 2006-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
|
||||
;; Maintainer: Simen Heggestøyl <simenheg@runbox.com>
|
||||
;; Keywords: hypermedia
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
(defconst css-pseudo-class-ids
|
||||
'("active" "checked" "default" "disabled" "empty" "enabled" "first"
|
||||
"first-child" "first-of-type" "focus" "focus-within" "hover"
|
||||
"first-child" "first-of-type" "focus" "focus-within" "has" "hover"
|
||||
"in-range" "indeterminate" "invalid" "lang" "last-child"
|
||||
"last-of-type" "left" "link" "not" "nth-child" "nth-last-child"
|
||||
"nth-last-of-type" "nth-of-type" "only-child" "only-of-type"
|
||||
|
|
|
|||
|
|
@ -390,6 +390,16 @@ which can be the value of the `face' text property."
|
|||
(list (list "x-color" (cadr face))))
|
||||
((and (listp face) (eq (car face) :background))
|
||||
(list (list "x-bg-color" (cadr face))))
|
||||
((and (listp face) (eq (car face) :underline))
|
||||
(list (list "underline")))
|
||||
((and (listp face)
|
||||
(eq (car face) :weight)
|
||||
(eq (cadr face) 'bold))
|
||||
(list (list "bold")))
|
||||
((and (listp face)
|
||||
(eq (car face) :slant)
|
||||
(memq (cadr face) '(italic oblique)))
|
||||
(list (list "italic")))
|
||||
((listp face)
|
||||
(apply #'append (mapcar #'enriched-face-ans face)))
|
||||
((let* ((fg (face-attribute face :foreground))
|
||||
|
|
|
|||
|
|
@ -1700,7 +1700,7 @@ and URL `https://rhodesmill.org/brandon/2012/one-sentence-per-line/'."
|
|||
(to (copy-marker (max from to) t))
|
||||
pfx)
|
||||
(goto-char from)
|
||||
(let ((fill-column (* 2 (point-max)))) ; Wide characters span up to two columns.
|
||||
(let ((fill-column most-positive-fixnum))
|
||||
(setq pfx (or (save-excursion
|
||||
(fill-region-as-paragraph-default (point)
|
||||
to
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
(require 'treesit)
|
||||
(require 'subr-x)
|
||||
(require 'outline)
|
||||
(require 'seq)
|
||||
|
||||
(treesit-declare-unavailable-functions)
|
||||
|
||||
|
|
@ -296,7 +297,12 @@ the same features enabled in MODE."
|
|||
(plist-get configs :simple-indent)))
|
||||
(setq treesit-range-settings
|
||||
(append treesit-range-settings
|
||||
(plist-get configs :range)))
|
||||
;; Filter out function queries, because they are
|
||||
;; usually some hack and might escape the code block.
|
||||
;; Case in point: c-ts-mode's range setting.
|
||||
(seq-filter (lambda (setting)
|
||||
(not (functionp (car setting))))
|
||||
(plist-get configs :range))))
|
||||
(setq-local indent-line-function #'treesit-indent)
|
||||
(setq-local indent-region-function #'treesit-indent-region)))
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ with %, which are converted as follows:
|
|||
%H 24-hour clock hour %I 12-hour clock hour
|
||||
%m month number
|
||||
%M minute
|
||||
%p meridian indicator: `AM', `PM'
|
||||
%p meridiem indicator: `AM', `PM'
|
||||
%S seconds
|
||||
%w day number of week, Sunday is 0
|
||||
%Y 4-digit year %y 2-digit year
|
||||
|
|
@ -1039,39 +1039,45 @@ This is an internal function called by `time-stamp'."
|
|||
offset-secs)
|
||||
"Format a time offset according to a %z variation.
|
||||
|
||||
With no flags, the output includes hours and minutes: +-HHMM
|
||||
unless there is a non-zero seconds part, in which case the seconds
|
||||
are included: +-HHMMSS
|
||||
|
||||
FLAG-MINIMIZE is whether \"-\" was specified. If non-nil, the
|
||||
output may be limited to hours if minutes and seconds are zero.
|
||||
|
||||
FLAG-PAD-SPACES-ONLY is whether \"_\" was specified. If non-nil,
|
||||
seconds must be output, so that any padding can be spaces only.
|
||||
|
||||
FLAG-PAD-ZEROS-FIRST is whether \"0\" was specified. If non-nil,
|
||||
padding to the requested FIELD-WIDTH (if any) is done by adding
|
||||
00 seconds before padding with spaces.
|
||||
|
||||
COLON-COUNT is the number of colons preceding the \"z\" (0-3). One or
|
||||
two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS).
|
||||
Three colons outputs only hours if minutes and seconds are zero and
|
||||
includes colon separators if minutes and seconds are output.
|
||||
|
||||
FIELD-WIDTH is a whole number giving the minimum number of characters
|
||||
in the output; 0 specifies no minimum. Additional characters will be
|
||||
added on the right if necessary. The added characters will be spaces
|
||||
unless FLAG-PAD-ZEROS-FIRST is non-nil.
|
||||
|
||||
OFFSET-SECS is the time zone offset (in seconds east of UTC) to be
|
||||
formatted according to the preceding parameters.
|
||||
Format parts FLAG-MINIMIZE, FLAG-PAD-SPACES-ONLY,
|
||||
FLAG-PAD-ZEROS-FIRST, COLON-COUNT, and FIELD-WIDTH
|
||||
are used to format time zone offset OFFSET-SECS.
|
||||
|
||||
This is an internal function used by `time-stamp'."
|
||||
|
||||
;; Callers of this function need to have already parsed the %z
|
||||
;; format string; this function accepts just the parts of the format.
|
||||
;; `time-stamp-string-preprocess' is the full-fledged parser normally
|
||||
;; used. The unit test (in time-stamp-tests.el) defines the simpler
|
||||
;; parser `format-time-offset'.
|
||||
|
||||
;; OFFSET-SECS is the time zone offset (in seconds east of UTC) to be
|
||||
;; formatted according to the following parameters.
|
||||
|
||||
;; FLAG-MINIMIZE is whether \"-\" was specified. If non-nil, the
|
||||
;; output may be limited to hours if minutes and seconds are zero.
|
||||
|
||||
;; FLAG-PAD-SPACES-ONLY is whether \"_\" was specified. If non-nil,
|
||||
;; seconds must be output, so that any padding can be spaces only.
|
||||
|
||||
;; FLAG-PAD-ZEROS-FIRST is whether \"0\" was specified. If non-nil,
|
||||
;; padding to the requested FIELD-WIDTH (if any) is done by adding
|
||||
;; 00 seconds before padding with spaces.
|
||||
|
||||
;; COLON-COUNT is the number of colons preceding the \"z\" (0-3). One or
|
||||
;; two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS).
|
||||
;; Three colons outputs only hours if minutes and seconds are zero and
|
||||
;; includes colon separators if minutes and seconds are output.
|
||||
|
||||
;; FIELD-WIDTH is a whole number giving the minimum number of characters
|
||||
;; in the output; 0 specifies no minimum. Additional characters will be
|
||||
;; added on the right if necessary. The added characters will be spaces
|
||||
;; unless FLAG-PAD-ZEROS-FIRST is non-nil.
|
||||
|
||||
;; With no flags set, the output includes hours and minutes: +-HHMM
|
||||
;; unless there is a non-zero seconds part, in which case the seconds
|
||||
;; are included: +-HHMMSS
|
||||
|
||||
(let ((hrs (/ (abs offset-secs) 3600))
|
||||
(mins (/ (% (abs offset-secs) 3600) 60))
|
||||
(secs (% (abs offset-secs) 60))
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ holds a keymap."
|
|||
:vert-only t)
|
||||
(tool-bar-add-item-from-menu 'menu-find-file-existing "open" nil
|
||||
:label "Open" :vert-only t)
|
||||
(tool-bar-add-item-from-menu 'dired "diropen" nil :vert-only t)
|
||||
(tool-bar-add-item-from-menu 'dired-from-menubar "diropen" nil :vert-only t)
|
||||
(tool-bar-add-item-from-menu 'kill-this-buffer "close" nil :vert-only t)
|
||||
(tool-bar-add-item-from-menu 'save-buffer "save" nil
|
||||
:label "Save")
|
||||
|
|
|
|||
|
|
@ -753,10 +753,10 @@ that encompasses the region between START and END."
|
|||
(numberp (cdr range-offset)))
|
||||
(signal 'treesit-error (list "Value of :offset option should be a pair of numbers" range-offset)))
|
||||
(setq offset range-offset)))
|
||||
(:range-fn (let ((range-fn (pop query-specs)))
|
||||
(unless (functionp range-fn)
|
||||
(signal 'treesit-error (list "Value of :range-fn option should be a function" range-fn)))
|
||||
(setq range-fn range-fn)))
|
||||
(:range-fn (let ((fn (pop query-specs)))
|
||||
(unless (functionp fn)
|
||||
(signal 'treesit-error (list "Value of :range-fn option should be a function" fn)))
|
||||
(setq range-fn fn)))
|
||||
(query (if (functionp query)
|
||||
(push (list query nil nil) result)
|
||||
(when (null embed)
|
||||
|
|
@ -1423,22 +1423,31 @@ LANGUAGE is the language of QUERY.")
|
|||
(setf (nth 1 new-setting) t)
|
||||
new-setting))
|
||||
|
||||
(defun treesit--font-lock-level-setter (sym val)
|
||||
(defun treesit--font-lock-level-setter (sym val &optional buffer-local)
|
||||
"Custom setter for `treesit-font-lock-level'.
|
||||
Set the default value of SYM to VAL, recompute fontification
|
||||
features and refontify for every buffer where tree-sitter-based
|
||||
fontification is enabled."
|
||||
(set-default sym val)
|
||||
(when (treesit-available-p)
|
||||
(dolist (buffer (buffer-list))
|
||||
(with-current-buffer buffer
|
||||
;; FIXME: This doesn't re-run major mode hooks, meaning any
|
||||
;; customization done in major mode hooks (e.g., with
|
||||
;; `treesit-font-lock-recompute-features') is lost.
|
||||
(when treesit-font-lock-settings
|
||||
(treesit-font-lock-recompute-features)
|
||||
(treesit-font-lock-fontify-region
|
||||
(point-min) (point-max)))))))
|
||||
fontification is enabled.
|
||||
|
||||
If optional BUFFER-LOCAL is non-nil, only affect the current buffer.
|
||||
Set SYM buffer locally and refontify."
|
||||
;; FIXME: This doesn't re-run major mode hooks, meaning any
|
||||
;; customization done in major mode hooks (e.g., with
|
||||
;; `treesit-font-lock-recompute-features') may be overridden.
|
||||
(cond (buffer-local
|
||||
(set-local sym val)
|
||||
(when (and (treesit-available-p)
|
||||
treesit-font-lock-settings)
|
||||
(treesit-font-lock-recompute-features)
|
||||
(font-lock-flush)))
|
||||
(t
|
||||
(set-default sym val)
|
||||
(when (treesit-available-p)
|
||||
(dolist (buffer (buffer-list))
|
||||
(with-current-buffer buffer
|
||||
(when treesit-font-lock-settings
|
||||
(treesit-font-lock-recompute-features)
|
||||
(font-lock-flush))))))))
|
||||
|
||||
(defcustom treesit-font-lock-level 3
|
||||
"Decoration level to be used by tree-sitter fontifications.
|
||||
|
|
@ -2050,9 +2059,8 @@ If LOUDLY is non-nil, display some debugging information."
|
|||
(pcase-let ((`(,max-depth ,max-width)
|
||||
(treesit-subtree-stat
|
||||
(treesit-buffer-root-node language))))
|
||||
(if (or (> max-depth 100) (> max-width 4000))
|
||||
(setq treesit--font-lock-fast-mode t)
|
||||
(setq treesit--font-lock-fast-mode nil))))
|
||||
(setq treesit--font-lock-fast-mode
|
||||
(or (> max-depth 100) (> max-width 4000)))))
|
||||
|
||||
;; Only activate if ENABLE flag is t.
|
||||
(when-let*
|
||||
|
|
@ -5849,7 +5857,7 @@ language."
|
|||
"Pattern matching"
|
||||
(treesit-query-capture
|
||||
:no-eval (treesit-query-capture node '((identifier) @id "return" @ret))
|
||||
:eg-result-string "((id . #<treesit-node (identifier) in 195-196>) (ret . #<treesit-node "return" in 338-344>))")
|
||||
:eg-result-string "((id . #<treesit-node (identifier) in 195-196>) (ret . #<treesit-node \"return\" in 338-344>))")
|
||||
(treesit-query-compile
|
||||
:no-eval (treesit-query-compile 'c '((identifier) @id "return" @ret))
|
||||
:eg-result-string "#<treesit-compiled-query>")
|
||||
|
|
|
|||
|
|
@ -977,6 +977,7 @@ In the latter case, VC mode is deactivated for this buffer."
|
|||
noninteractive
|
||||
;; Copied from server-start. Seems like there should
|
||||
;; be a better way to ask "can we get user input?"...
|
||||
;; Use `frame-initial-p'?
|
||||
(and (daemonp)
|
||||
(null (cdr (frame-list)))
|
||||
(eq (selected-frame) terminal-frame))
|
||||
|
|
|
|||
|
|
@ -907,9 +907,9 @@ means that `whitespace-mode' is turned on for buffers in C and
|
|||
C++ modes only.
|
||||
|
||||
Global `whitespace-mode' will not automatically turn on in internal
|
||||
buffers (with name starting from space) and special buffers (with name
|
||||
starting from \"*\"), except \"*scratch*\" buffer. Use
|
||||
`whitespace-global-mode-buffers' to customize this behavior."
|
||||
buffers (whose names start with a space) and special buffers (whose
|
||||
names start with \"*\"), with the exception of the \"*scratch*\" buffer.
|
||||
Use `whitespace-global-mode-buffers' to customize this behavior."
|
||||
:type '(choice :tag "Global Modes"
|
||||
(const :tag "None" nil)
|
||||
(const :tag "All" t)
|
||||
|
|
@ -919,11 +919,11 @@ starting from \"*\"), except \"*scratch*\" buffer. Use
|
|||
(repeat :inline t
|
||||
(symbol :tag "Mode")))))
|
||||
|
||||
(defcustom whitespace-global-mode-buffers (list (regexp-quote "*scratch*"))
|
||||
(defcustom whitespace-global-mode-buffers (list (rx bos "*scratch*" eos))
|
||||
"Buffer name regexps where global `whitespace-mode' can be auto-enabled.
|
||||
The value is a list of regexps. Set this custom option when you need
|
||||
`whitespace-mode' in special buffers like *Org Src*."
|
||||
:type '(list (regexp :tag "Regexp matching buffer name"))
|
||||
`whitespace-mode' in special buffers like \"*Org Src*\"."
|
||||
:type '(repeat (regexp :tag "Regexp matching buffer name"))
|
||||
:version "31.1")
|
||||
|
||||
(defcustom whitespace-action nil
|
||||
|
|
@ -1049,14 +1049,13 @@ See also `whitespace-newline' and `whitespace-display-mappings'."
|
|||
;; ...we have a display (not running a batch job)
|
||||
(not noninteractive)
|
||||
;; ...the buffer is not internal (name starts with a space)
|
||||
(not (eq (aref (buffer-name) 0) ?\ ))
|
||||
(not (eq (aref (buffer-name) 0) ?\s))
|
||||
;; ...the buffer is not special (name starts with *)
|
||||
(or (not (eq (aref (buffer-name) 0) ?*))
|
||||
;; except the scratch buffer.
|
||||
(seq-find
|
||||
(lambda (re)
|
||||
(string-match-p re (buffer-name)))
|
||||
whitespace-global-mode-buffers))))
|
||||
;; except, e.g., the scratch buffer.
|
||||
(any (lambda (re)
|
||||
(string-match-p re (buffer-name)))
|
||||
whitespace-global-mode-buffers))))
|
||||
"Predicate to decide which buffers obey `global-whitespace-mode'.
|
||||
This function is called with no argument and should return non-nil
|
||||
if the current buffer should obey `global-whitespace-mode'.
|
||||
|
|
|
|||
|
|
@ -1010,6 +1010,14 @@ and may be called only if no window on SIDE exists yet."
|
|||
(cons `(dedicated . ,(or display-buffer-mark-dedicated 'side))
|
||||
alist))))
|
||||
(when window
|
||||
;; Protect the sibling (the main-window group) from recombination.
|
||||
;; Without this, deleting a side window can flatten the group into
|
||||
;; the root, causing subsequent side windows on other sides to be
|
||||
;; placed incorrectly (Bug#80665).
|
||||
(when-let* ((sibling (or (window-prev-sibling window)
|
||||
(window-next-sibling window)))
|
||||
((window-child sibling)))
|
||||
(set-window-combination-limit sibling t))
|
||||
;; Initialize `window-side' parameter of new window to SIDE and
|
||||
;; make that parameter persistent.
|
||||
(set-window-parameter window 'window-side side)
|
||||
|
|
|
|||
|
|
@ -509,16 +509,14 @@ enable, ?l to disable)."
|
|||
"Enable xterm mouse tracking on TERMINAL."
|
||||
(when (and xterm-mouse-mode (eq t (terminal-live-p terminal))
|
||||
;; Avoid the initial terminal which is not a termcap device.
|
||||
;; FIXME: is there more elegant way to detect the initial
|
||||
;; terminal?
|
||||
(not (string= (terminal-name terminal) "initial_terminal")))
|
||||
(not (frame-initial-p terminal)))
|
||||
(unless (terminal-parameter terminal 'xterm-mouse-mode)
|
||||
;; Simulate selecting a terminal by selecting one of its frames
|
||||
;; so that we can set the terminal-local `input-decode-map'.
|
||||
;; Use the tty-top-frame to avoid accidentally making an invisible
|
||||
;; child frame visible by selecting it (bug#79960).
|
||||
;; The test for match mode is here because xt-mouse-tests run in
|
||||
;; match mode, and there is no top-frame in that case.
|
||||
;; The test for batch mode is here because xt-mouse-tests run in
|
||||
;; batch mode, and there is no top-frame in that case.
|
||||
(with-selected-frame (if noninteractive
|
||||
(car (frame-list))
|
||||
(tty-top-frame terminal))
|
||||
|
|
|
|||
10
src/bidi.c
10
src/bidi.c
|
|
@ -367,6 +367,8 @@ bidi_isolate_fmt_char (bidi_type_t ch_type)
|
|||
return (ch_type == LRI || ch_type == RLI || ch_type == PDI || ch_type == FSI);
|
||||
}
|
||||
|
||||
static void bidi_initialize (void);
|
||||
|
||||
/* Return the mirrored character of C, if it has one. If C has no
|
||||
mirrored counterpart, return C.
|
||||
Note: The conditions in UAX#9 clause L4 regarding the surrounding
|
||||
|
|
@ -381,6 +383,14 @@ bidi_mirror_char (int c)
|
|||
if (c < 0 || c > MAX_CHAR)
|
||||
emacs_abort ();
|
||||
|
||||
/* We can be called at the very beginning of init_iterator, via
|
||||
produce_special_glyphs, and the first such call in a session might
|
||||
happen when the bidi-mirroring table was not yet initialized. Make
|
||||
sure we do this now. */
|
||||
if (!CHAR_TABLE_P (bidi_mirror_table)
|
||||
&& !bidi_initialized)
|
||||
bidi_initialize ();
|
||||
|
||||
val = CHAR_TABLE_REF (bidi_mirror_table, c);
|
||||
if (FIXNUMP (val))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -799,7 +799,7 @@ Optional 4th and 5th arguments FROM-CODE and TO-CODE specify the
|
|||
range of code points (in CHARSET) of target characters on which to
|
||||
map the FUNCTION. Note that these are not character codes, but code
|
||||
points of CHARSET; for the difference see `decode-char' and
|
||||
`list-charset-chars'. If FROM-CODE is nil or imitted, it stands for
|
||||
`list-charset-chars'. If FROM-CODE is nil or omitted, it stands for
|
||||
the first code point of CHARSET; if TO-CODE is nil or omitted, it
|
||||
stands for the last code point of CHARSET.
|
||||
|
||||
|
|
@ -840,7 +840,7 @@ TO-CODE, which are CHARSET code points. */)
|
|||
/* Define a charset according to the arguments. The Nth argument is
|
||||
the Nth attribute of the charset (the last attribute `charset-id'
|
||||
is not included). See the docstring of `define-charset' for the
|
||||
detail. */
|
||||
details. */
|
||||
|
||||
DEFUN ("define-charset-internal", Fdefine_charset_internal,
|
||||
Sdefine_charset_internal, charset_arg_max, MANY, 0,
|
||||
|
|
@ -1530,7 +1530,7 @@ BEG and END are buffer positions.
|
|||
Optional arg TABLE if non-nil is a translation table to look up.
|
||||
|
||||
If the current buffer is unibyte, the returned list may contain
|
||||
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */)
|
||||
only `ascii' and `eight-bit'. */)
|
||||
(Lisp_Object beg, Lisp_Object end, Lisp_Object table)
|
||||
{
|
||||
Lisp_Object charsets;
|
||||
|
|
@ -1581,7 +1581,7 @@ DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string,
|
|||
Optional arg TABLE if non-nil is a translation table to look up.
|
||||
|
||||
If STR is unibyte, the returned list may contain
|
||||
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */)
|
||||
only `ascii' and `eight-bit'. */)
|
||||
(Lisp_Object str, Lisp_Object table)
|
||||
{
|
||||
CHECK_STRING (str);
|
||||
|
|
@ -2036,7 +2036,7 @@ ASCII characters are an exception: for them, this function always
|
|||
returns `ascii'.
|
||||
If optional 2nd arg RESTRICTION is non-nil, it is a list of charsets
|
||||
from which to find the charset. It may also be a coding system. In
|
||||
that case, find the charset from what supported by that coding system. */)
|
||||
that case, find the charset in those supported by that coding system. */)
|
||||
(Lisp_Object ch, Lisp_Object restriction)
|
||||
{
|
||||
struct charset *charset;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ sub_char_table_ref_and_range (Lisp_Object, int, int *, int *,
|
|||
/* Nonzero iff OBJ is a string representing uniprop values of 128
|
||||
succeeding characters (the bottom level of a char-table) by a
|
||||
compressed format. We are sure that no property value has a string
|
||||
starting with '\001' nor '\002'. */
|
||||
starting with '\001' or '\002'. */
|
||||
#define UNIPROP_COMPRESSED_FORM_P(OBJ) \
|
||||
(STRINGP (OBJ) && SCHARS (OBJ) > 0 \
|
||||
&& ((SREF (OBJ, 0) == 1 || (SREF (OBJ, 0) == 2))))
|
||||
|
|
|
|||
|
|
@ -6826,8 +6826,7 @@ FILE = nil means just close any termscript file currently open. */)
|
|||
{
|
||||
struct tty_display_info *tty;
|
||||
|
||||
if (! FRAME_TERMCAP_P (SELECTED_FRAME ())
|
||||
&& ! FRAME_MSDOS_P (SELECTED_FRAME ()))
|
||||
if (!is_tty_frame (SELECTED_FRAME ()))
|
||||
error ("Current frame is not on a tty device");
|
||||
|
||||
tty = CURTTY ();
|
||||
|
|
@ -7394,7 +7393,7 @@ init_display_interactive (void)
|
|||
t = init_tty (0, terminal_type, 1); /* Errors are fatal. */
|
||||
|
||||
/* Convert the initial frame to use the new display. */
|
||||
if (f->output_method != output_initial)
|
||||
if (!FRAME_INITIAL_P (f))
|
||||
emacs_abort ();
|
||||
f->output_method = t->type;
|
||||
f->terminal = t;
|
||||
|
|
@ -7404,7 +7403,7 @@ init_display_interactive (void)
|
|||
f->output_data.tty = &the_only_tty_output;
|
||||
f->output_data.tty->display_info = &the_only_display_info;
|
||||
#else
|
||||
if (f->output_method == output_termcap)
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
create_tty_output (f);
|
||||
#endif
|
||||
t->display_info.tty->top_frame = selected_frame;
|
||||
|
|
|
|||
|
|
@ -681,8 +681,7 @@ dos_cleanup (void)
|
|||
{
|
||||
struct frame *sf = XFRAME (selected_frame);
|
||||
|
||||
if (FRAME_LIVE_P (sf)
|
||||
&& (FRAME_MSDOS_P (sf) || FRAME_TERMCAP_P (sf)))
|
||||
if (FRAME_LIVE_P (sf) && is_tty_frame (sf))
|
||||
{
|
||||
tty = CURTTY ();
|
||||
if (tty->termscript)
|
||||
|
|
|
|||
|
|
@ -774,6 +774,9 @@ Do not expand PREFIX; a non-absolute PREFIX is relative to the Emacs
|
|||
working directory. If TEXT is a string, insert it into the newly
|
||||
created file.
|
||||
|
||||
On Posix systems, the file/directory is created with access mode bits
|
||||
that limit access to the current user.
|
||||
|
||||
Signal an error if the file could not be created.
|
||||
|
||||
This function does not grok magic file names. */)
|
||||
|
|
|
|||
17
src/frame.c
17
src/frame.c
|
|
@ -214,7 +214,7 @@ frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
|
|||
&& !NILP (fullscreen) && !EQ (fullscreen, Qfullheight))
|
||||
|| (!horizontal
|
||||
&& !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth))
|
||||
|| FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))));
|
||||
|| is_tty_frame (f))));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -349,8 +349,6 @@ If FRAME is nil, use the selected frame.
|
|||
Return nil if the id has not been set. */)
|
||||
(Lisp_Object frame)
|
||||
{
|
||||
if (NILP (frame))
|
||||
frame = selected_frame;
|
||||
struct frame *f = decode_live_frame (frame);
|
||||
if (f->id == 0)
|
||||
return Qnil;
|
||||
|
|
@ -562,7 +560,7 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
|
|||
|
||||
/* Don't allow too small height of text-mode frames, or else cm.c
|
||||
might abort in cmcheckmagic. */
|
||||
if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
|
||||
if (is_tty_frame (f) && NILP (horizontal))
|
||||
{
|
||||
int min_height = (FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)
|
||||
+ FRAME_WANTS_MODELINE_P (f)
|
||||
|
|
@ -1573,7 +1571,7 @@ make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
|
|||
f->output_data.tty->display_info = &the_only_display_info;
|
||||
if (!inhibit_window_system
|
||||
&& (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
|
||||
|| XFRAME (selected_frame)->output_method == output_msdos_raw))
|
||||
|| FRAME_MSDOS_P (XFRAME (selected_frame))))
|
||||
f->output_method = output_msdos_raw;
|
||||
else
|
||||
f->output_method = output_termcap;
|
||||
|
|
@ -1763,13 +1761,12 @@ affects all frames on the same terminal device. */)
|
|||
struct frame *sf = SELECTED_FRAME ();
|
||||
|
||||
#ifdef MSDOS
|
||||
if (sf->output_method != output_msdos_raw
|
||||
&& sf->output_method != output_termcap)
|
||||
if (!is_tty_frame (sf))
|
||||
emacs_abort ();
|
||||
#else /* not MSDOS */
|
||||
|
||||
#ifdef WINDOWSNT /* This should work now! */
|
||||
if (sf->output_method != output_termcap)
|
||||
if (!FRAME_TERMCAP_P (sf))
|
||||
error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
|
||||
#endif
|
||||
#endif /* not MSDOS */
|
||||
|
|
@ -1986,7 +1983,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
|
|||
if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
|
||||
resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
|
||||
|
||||
if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
|
||||
if (is_tty_frame (f))
|
||||
{
|
||||
struct tty_display_info *tty = FRAME_TTY (f);
|
||||
Lisp_Object top_frame = tty->top_frame;
|
||||
|
|
@ -2800,7 +2797,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
&& FRAME_LIVE_P (f1)
|
||||
&& !FRAME_TOOLTIP_P (f1))
|
||||
{
|
||||
if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
|
||||
if (is_tty_frame (f1))
|
||||
{
|
||||
Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
|
||||
|
||||
|
|
|
|||
|
|
@ -2453,7 +2453,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
|
|||
#else
|
||||
struct frame *frame = XFRAME (selected_frame);
|
||||
struct terminal *terminal = frame->terminal;
|
||||
if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame))
|
||||
if (!(is_tty_frame (frame)
|
||||
/* Don't apply decoding if we're just reading a raw event
|
||||
(e.g. reading bytes sent by the xterm to specify the position
|
||||
of a mouse click). */
|
||||
|
|
@ -13032,7 +13032,7 @@ The elements of this list correspond to the arguments of
|
|||
|
||||
Lisp_Object interrupt = interrupt_input ? Qt : Qnil;
|
||||
Lisp_Object flow, meta;
|
||||
if (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
|
||||
if (is_tty_frame (sf))
|
||||
{
|
||||
flow = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
|
||||
meta = (FRAME_TTY (sf)->meta_key == 2
|
||||
|
|
|
|||
|
|
@ -5754,7 +5754,7 @@ extern void *w32_daemon_event;
|
|||
/* True if handling a fatal error already. */
|
||||
extern bool fatal_error_in_progress;
|
||||
|
||||
/* True means don't do use window-system-specific display code. */
|
||||
/* True means don't use window-system-specific display code. */
|
||||
extern bool inhibit_window_system;
|
||||
/* True means that a filter or a sentinel is running. */
|
||||
extern bool running_asynch_code;
|
||||
|
|
|
|||
|
|
@ -405,8 +405,7 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk
|
|||
}
|
||||
}
|
||||
|
||||
if ((FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
|
||||
|| FRAME_MSDOS_P (XFRAME (Vmenu_updating_frame)))
|
||||
if (is_tty_frame (XFRAME (Vmenu_updating_frame))
|
||||
&& !NILP (map))
|
||||
/* Indicate visually that this is a submenu. */
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1787,7 +1787,7 @@ internal_terminal_init (void)
|
|||
#endif
|
||||
|
||||
/* If this is the initial terminal, we are done here. */
|
||||
if (sf->output_method == output_initial)
|
||||
if (FRAME_INITIAL_P (sf))
|
||||
return;
|
||||
|
||||
internal_terminal
|
||||
|
|
|
|||
197
src/nsterm.m
197
src/nsterm.m
|
|
@ -72,6 +72,12 @@ Updated by Christian Limpach (chris@nice.ch)
|
|||
#include "macfont.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <IOSurface/IOSurface.h>
|
||||
/* ApplicationServices provides the macOS accessibility Zoom API
|
||||
UAZoomEnabled and UAZoomChangeFocus (UniversalAccess framework).
|
||||
Carbon.h already pulls in ApplicationServices on most SDK versions,
|
||||
but the explicit import makes the dependency visible and guards
|
||||
against SDK changes. */
|
||||
#import <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
static EmacsMenu *dockMenu;
|
||||
|
|
@ -1086,6 +1092,126 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
|||
[view lockFocus];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
macOS Accessibility Zoom Support
|
||||
-------------------------------------------------------------------------- */
|
||||
#ifdef NS_IMPL_COCOA
|
||||
|
||||
static BOOL ns_is_UAZoomEnabled = NO;
|
||||
static unsigned long ns_UAZoomEnabled_last_called_time_ns = 0;
|
||||
static const unsigned long NS_UAZOOMENABLED_CACHE_INTERVAL_NS =
|
||||
(unsigned long)(500 * NSEC_PER_MSEC); /* 500ms. */
|
||||
static NSTimeInterval NS_UAZOOMENABLED_DEFER_INTERVAL_SECS = 0.2; /* 200ms. */
|
||||
static NSTimer *ns_deferred_UAZoomChangeFocus_timer = nil;
|
||||
|
||||
static BOOL
|
||||
ns_ua_zoom_enabled_p (void)
|
||||
/* --------------------------------------------------------------------------
|
||||
Return the cached result of UAZoomEnabled. Refresh the cache every
|
||||
NS_UAZOOMENABLED_CACHE_INTERVAL_NS nanoseconds.
|
||||
|
||||
We cache the result to avoid the macOS Mach IPC Accessibility Server
|
||||
round trip cost on every Emacs cursor update. Since enabling Zoom
|
||||
requires an explicit user UI action that takes real user time, the
|
||||
cache TTL should be invisible to the user.
|
||||
|
||||
Use clock_gettime_nsec_np not CFAbsoluteTimeGetCurrent which depends
|
||||
on the wall clock which can be reset by the user or by NTP.
|
||||
|
||||
Main-thread-only and called from ns_update_end, below.
|
||||
-------------------------------------------------------------------------- */
|
||||
{
|
||||
/* User-space equivalent to mach_absolute_time. */
|
||||
unsigned long now_ns = clock_gettime_nsec_np (CLOCK_UPTIME_RAW);
|
||||
if (now_ns - ns_UAZoomEnabled_last_called_time_ns
|
||||
> NS_UAZOOMENABLED_CACHE_INTERVAL_NS)
|
||||
{
|
||||
ns_is_UAZoomEnabled = UAZoomEnabled ();
|
||||
ns_UAZoomEnabled_last_called_time_ns = now_ns;
|
||||
}
|
||||
return ns_is_UAZoomEnabled;
|
||||
}
|
||||
|
||||
static inline CGRect
|
||||
ns_cg_rect_flip_y (CGRect r)
|
||||
/* --------------------------------------------------------------------------
|
||||
Convert a CGRect from Cocoa screen coordinates (origin at bottom-left
|
||||
of the primary display) to CoreGraphics coordinates (origin at
|
||||
top-left of the primary display). CoreGraphics defines its
|
||||
coordinate origin at the top-left corner of the primary display and
|
||||
all screens share this global coordinate space, so the flip always
|
||||
uses the primary display height regardless of which screen R is on.
|
||||
-------------------------------------------------------------------------- */
|
||||
{
|
||||
CGDirectDisplayID mainID = CGMainDisplayID ();
|
||||
if (mainID == kCGNullDirectDisplay)
|
||||
return r;
|
||||
CGFloat primaryH = CGDisplayBounds (mainID).size.height;
|
||||
if (primaryH <= 0)
|
||||
return r;
|
||||
r.origin.y = primaryH - r.origin.y - r.size.height;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Cache cursor rects to call UAZoomChangeFocus only when the cursor
|
||||
position has changed, not merely when the cursor is blinking.
|
||||
See ns_draw_window_cursor and ns_update_end. */
|
||||
static NSRect ns_UAZoom_cursor_rect_new;
|
||||
static NSRect ns_UAZoom_cursor_rect_old;
|
||||
|
||||
/* Track Zoom state per display cycle. Update the macOS Zoom cursor
|
||||
position when Zoom transitions to enabled. */
|
||||
static BOOL ns_update_was_UAZoomEnabled = NO;
|
||||
|
||||
static void
|
||||
ns_UAZoomChangeFocus (EmacsView *view, BOOL force)
|
||||
/* --------------------------------------------------------------------------
|
||||
Advise macOS Accessibility Zoom UAZoomChangeFocus of a potentially
|
||||
new cursor position. Force an updated position when Zoom transitions
|
||||
to enabled, or when the frame gets focus.
|
||||
-------------------------------------------------------------------------- */
|
||||
{
|
||||
if (ns_ua_zoom_enabled_p ())
|
||||
{
|
||||
force = force || !ns_update_was_UAZoomEnabled;
|
||||
ns_update_was_UAZoomEnabled = YES;
|
||||
if (NSIsEmptyRect (ns_UAZoom_cursor_rect_new))
|
||||
return;
|
||||
if (force || !NSEqualRects (ns_UAZoom_cursor_rect_new,
|
||||
ns_UAZoom_cursor_rect_old))
|
||||
{
|
||||
ns_UAZoom_cursor_rect_old = ns_UAZoom_cursor_rect_new;
|
||||
NSRect windowRect = [view convertRect:ns_UAZoom_cursor_rect_new
|
||||
toView:nil];
|
||||
NSRect screenRect = [[view window] convertRectToScreen:windowRect];
|
||||
CGRect cgRect = ns_cg_rect_flip_y (NSRectToCGRect (screenRect));
|
||||
/* Some versions of macOS can ignore tiny rects, so we
|
||||
slightly expand a tiny one. Since we care mostly about its
|
||||
origin, this should be innocuous. */
|
||||
cgRect.size.width = MAX (cgRect.size.width, 6);
|
||||
cgRect.size.height = MAX (cgRect.size.height, 10);
|
||||
if (force)
|
||||
{
|
||||
/* UAZoomChangeFocus needs old and new cursor positions to
|
||||
be different, and also it sometimes needs a kick. In
|
||||
both cases, we fake a cursor move followed by the real
|
||||
cursor move. */
|
||||
CGRect cgRectJiggle = CGRectOffset (cgRect, 1.0, 1.0);
|
||||
if (UAZoomChangeFocus (&cgRectJiggle, NULL,
|
||||
kUAZoomFocusTypeInsertionPoint))
|
||||
NSLog (@"UAZoomChangeFocus jiggle failed");
|
||||
}
|
||||
if (UAZoomChangeFocus (&cgRect, NULL,
|
||||
kUAZoomFocusTypeInsertionPoint))
|
||||
NSLog (@"UAZoomChangeFocus failed");
|
||||
NSAccessibilityPostNotification
|
||||
(view, NSAccessibilityFocusedUIElementChangedNotification);
|
||||
}
|
||||
}
|
||||
else
|
||||
ns_update_was_UAZoomEnabled = NO;
|
||||
}
|
||||
#endif /* NS_IMPL_COCOA */
|
||||
|
||||
static void
|
||||
ns_update_end (struct frame *f)
|
||||
|
|
@ -1108,6 +1234,10 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
|
|||
[[view window] flushWindow];
|
||||
#endif
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
ns_UAZoomChangeFocus (view, false);
|
||||
#endif
|
||||
|
||||
unblock_input ();
|
||||
ns_updating_frame = NULL;
|
||||
}
|
||||
|
|
@ -3238,6 +3368,16 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
|
|||
/* Prevent the cursor from being drawn outside the text area. */
|
||||
r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA));
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
/* Cache the cursor rect for macOS Accessibility Zoom integration (see
|
||||
ns_update_end). Only store the rect for the active cursor ---
|
||||
inactive windows must not overwrite the value because redisplay may
|
||||
draw multiple windows per frame and the drawing order is not
|
||||
guaranteed. */
|
||||
if (active_p)
|
||||
ns_UAZoom_cursor_rect_new = r;
|
||||
#endif
|
||||
|
||||
ns_focus (f, NULL, 0);
|
||||
|
||||
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
|
||||
|
|
@ -6384,6 +6524,14 @@ - (void)applicationDidFinishLaunching: (NSNotification *)notification
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
/* Is accessibility enabled for this process/bundle? */
|
||||
if (AXIsProcessTrusted())
|
||||
NSLog (@"Emacs is macOS AXIsProcessTrusted");
|
||||
else
|
||||
NSLog (@"Emacs is not macOS AXIsProcessTrusted");
|
||||
#endif
|
||||
|
||||
ns_send_appdefined (-2);
|
||||
}
|
||||
|
||||
|
|
@ -7300,6 +7448,12 @@ - (NSRect) firstRectForCharacterRange: (NSRange) range
|
|||
return [self firstRectForCharacterRange: range];
|
||||
}
|
||||
|
||||
- (NSRect)accessibilityFrame
|
||||
{
|
||||
EmacsView *view = FRAME_NS_VIEW (*emacsframe);
|
||||
return [[view window] convertRectToScreen: ns_UAZoom_cursor_rect_new];
|
||||
}
|
||||
|
||||
#endif /* NS_IMPL_COCOA */
|
||||
|
||||
/***********************************************************************
|
||||
|
|
@ -8257,12 +8411,48 @@ - (void)windowDidBecomeKey /* for direct calls */
|
|||
ns_frame_rehighlight (*emacsframe);
|
||||
[self adjustEmacsFrameRect];
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
EmacsView *view = FRAME_NS_VIEW (*emacsframe);
|
||||
/* Make sure we have focus and the timer isn't already scheduled. */
|
||||
if (self.window.firstResponder == view
|
||||
&& !ns_deferred_UAZoomChangeFocus_timer)
|
||||
{
|
||||
/* Calls to ns_UAZoomChangeFocus are synchronous. We defer the
|
||||
call to give macOS time to finish window compositing or the
|
||||
calls can be silently ignored by the Zoom daemon and with no
|
||||
errors reported. This also helps ensure ns_draw_window_cursor
|
||||
has populated ns_UAZoom_cursor_rect_new. The 200 ms delay was
|
||||
chosen as a balance between macOS headroom and user
|
||||
perception. */
|
||||
ns_deferred_UAZoomChangeFocus_timer
|
||||
= [[NSTimer
|
||||
scheduledTimerWithTimeInterval:
|
||||
NS_UAZOOMENABLED_DEFER_INTERVAL_SECS
|
||||
target: self
|
||||
selector:
|
||||
@selector (deferred_UAZoomChangeFocus_handler:)
|
||||
userInfo: 0
|
||||
repeats: NO]
|
||||
retain];
|
||||
}
|
||||
#endif
|
||||
|
||||
event.kind = FOCUS_IN_EVENT;
|
||||
XSETFRAME (event.frame_or_window, *emacsframe);
|
||||
kbd_buffer_store_event (&event);
|
||||
ns_send_appdefined (-1); // Kick main loop
|
||||
}
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
- (void)deferred_UAZoomChangeFocus_handler: (NSTimer *)timer
|
||||
{
|
||||
EmacsView *view = FRAME_NS_VIEW (*emacsframe);
|
||||
ns_UAZoomChangeFocus (view, true);
|
||||
[ns_deferred_UAZoomChangeFocus_timer invalidate];
|
||||
[ns_deferred_UAZoomChangeFocus_timer release];
|
||||
ns_deferred_UAZoomChangeFocus_timer = nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)windowDidResignKey: (NSNotification *)notification
|
||||
/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
|
||||
|
|
@ -8365,6 +8555,13 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
|
|||
|
||||
FRAME_NS_VIEW (f) = self;
|
||||
*emacsframe = f;
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
/* macOS Accessibility Zoom Support. */
|
||||
ns_UAZoom_cursor_rect_new = NSZeroRect;
|
||||
ns_UAZoom_cursor_rect_old = NSZeroRect;
|
||||
#endif
|
||||
|
||||
#ifdef NS_IMPL_COCOA
|
||||
old_title = 0;
|
||||
maximizing_resize = NO;
|
||||
|
|
|
|||
|
|
@ -703,33 +703,16 @@ pgtk_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
|
|||
|
||||
static void
|
||||
pgtk_set_window_size (struct frame *f, bool change_gravity,
|
||||
int width, int height)
|
||||
int pixelwidth, int pixelheight)
|
||||
/* --------------------------------------------------------------------------
|
||||
Adjust window pixel size based on given character grid size
|
||||
Impl is a bit more complex than other terms, need to do some
|
||||
internal clipping.
|
||||
Adjust window pixel size based on given width and height.
|
||||
-------------------------------------------------------------------------- */
|
||||
{
|
||||
int pixelwidth, pixelheight;
|
||||
|
||||
block_input ();
|
||||
|
||||
gtk_widget_get_size_request (FRAME_GTK_WIDGET (f), &pixelwidth,
|
||||
&pixelheight);
|
||||
|
||||
pixelwidth = width;
|
||||
pixelheight = height;
|
||||
|
||||
for (GtkWidget * w = FRAME_GTK_WIDGET (f); w != NULL;
|
||||
w = gtk_widget_get_parent (w))
|
||||
{
|
||||
gint wd, hi;
|
||||
gtk_widget_get_size_request (w, &wd, &hi);
|
||||
}
|
||||
|
||||
f->output_data.pgtk->preferred_width = pixelwidth;
|
||||
f->output_data.pgtk->preferred_height = pixelheight;
|
||||
xg_wm_set_size_hint (f, 0, 0);
|
||||
|
||||
xg_frame_set_char_size (f, pixelwidth, pixelheight);
|
||||
gtk_widget_queue_resize (FRAME_WIDGET (f));
|
||||
|
||||
|
|
@ -5722,10 +5705,11 @@ pgtk_focus_changed (gboolean is_enter, int state,
|
|||
|
||||
/* Don't stop displaying the initial startup message
|
||||
for a switch-frame event we don't need. */
|
||||
/* When run as a daemon, Vterminal_frame is always NIL. */
|
||||
/* When run as a daemon, Vterminal_frame is always nil.
|
||||
FIXME: Isn't it actually the other way around? */
|
||||
bufp->ie.arg = (((NILP (Vterminal_frame)
|
||||
|| !FRAME_PGTK_P (XFRAME (Vterminal_frame))
|
||||
|| EQ (Fdaemonp (), Qt))
|
||||
|| IS_DAEMON)
|
||||
&& CONSP (Vframe_list)
|
||||
&& !NILP (XCDR (Vframe_list))) ? Qt : Qnil);
|
||||
bufp->ie.kind = FOCUS_IN_EVENT;
|
||||
|
|
|
|||
|
|
@ -1341,8 +1341,7 @@ init_sys_modes (struct tty_display_info *tty_out)
|
|||
frame_garbaged = 1;
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
if ((FRAME_TERMCAP_P (XFRAME (frame))
|
||||
|| FRAME_MSDOS_P (XFRAME (frame)))
|
||||
if (is_tty_frame (XFRAME (frame))
|
||||
&& FRAME_TTY (XFRAME (frame)) == tty_out)
|
||||
FRAME_GARBAGED_P (XFRAME (frame)) = 1;
|
||||
}
|
||||
|
|
|
|||
10
src/term.c
10
src/term.c
|
|
@ -2969,9 +2969,7 @@ Gpm-mouse can only be activated for one tty at a time. */)
|
|||
(void)
|
||||
{
|
||||
struct frame *f = SELECTED_FRAME ();
|
||||
struct tty_display_info *tty
|
||||
= ((f)->output_method == output_termcap
|
||||
? (f)->terminal->display_info.tty : NULL);
|
||||
struct tty_display_info *tty = FRAME_TERMCAP_P (f) ? FRAME_TTY (f) : NULL;
|
||||
Gpm_Connect connection;
|
||||
|
||||
if (!tty)
|
||||
|
|
@ -3017,9 +3015,7 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
|
|||
(void)
|
||||
{
|
||||
struct frame *f = SELECTED_FRAME ();
|
||||
struct tty_display_info *tty
|
||||
= ((f)->output_method == output_termcap
|
||||
? (f)->terminal->display_info.tty : NULL);
|
||||
struct tty_display_info *tty = FRAME_TERMCAP_P (f) ? FRAME_TTY (f) : NULL;
|
||||
|
||||
if (!tty || gpm_tty != tty)
|
||||
return Qnil; /* Not activated on this terminal, nothing to do. */
|
||||
|
|
@ -4214,7 +4210,7 @@ tty_free_frame_resources (struct frame *f)
|
|||
static void
|
||||
tty_free_frame_resources (struct frame *f)
|
||||
{
|
||||
eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
|
||||
eassert (is_tty_frame (f));
|
||||
free_frame_faces (f);
|
||||
/* Deleting a child frame means we have to thoroughly redisplay its
|
||||
root frame to make sure the child disappears from the display. */
|
||||
|
|
|
|||
|
|
@ -251,8 +251,8 @@ decode_live_terminal (Lisp_Object terminal)
|
|||
return t;
|
||||
}
|
||||
|
||||
/* Like decode_terminal, but ensure that the resulting terminal object refers
|
||||
to a text-based terminal device. */
|
||||
/* Like decode_live_terminal, but ensure that the resulting terminal
|
||||
object refers to a text-based terminal device. */
|
||||
|
||||
struct terminal *
|
||||
decode_tty_terminal (Lisp_Object terminal)
|
||||
|
|
@ -508,6 +508,25 @@ return values. */)
|
|||
}
|
||||
}
|
||||
|
||||
DEFUN ("frame-initial-p", Fframe_initial_p, Sframe_initial_p, 0, 1, 0,
|
||||
doc: /* Return non-nil if FRAME is the initial frame.
|
||||
That is, the initial text frame used internally during daemon mode,
|
||||
batch mode, and the early stages of startup.
|
||||
If FRAME is a terminal object, return non-nil if it holds
|
||||
the initial frame. FRAME defaults to the selected frame. */)
|
||||
(Lisp_Object frame)
|
||||
{
|
||||
if (NILP (frame))
|
||||
frame = selected_frame;
|
||||
if (FRAMEP (frame))
|
||||
{
|
||||
struct frame *f = XFRAME (frame);
|
||||
return FRAME_LIVE_P (f) && FRAME_INITIAL_P (f) ? Qt : Qnil;
|
||||
}
|
||||
struct terminal *t = decode_terminal (frame);
|
||||
return t && t->type == output_initial ? Qt : Qnil;
|
||||
}
|
||||
|
||||
DEFUN ("terminal-list", Fterminal_list, Sterminal_list, 0, 0, 0,
|
||||
doc: /* Return a list of all terminal devices. */)
|
||||
(void)
|
||||
|
|
@ -680,8 +699,6 @@ init_initial_terminal (void)
|
|||
#else
|
||||
initial_terminal_lisp = make_lisp_ptr (create_terminal (output_initial, NULL), Lisp_Vectorlike);
|
||||
#endif
|
||||
/* Note: menu-bar.el:menu-bar-update-buffers knows about this
|
||||
special name of the initial terminal. */
|
||||
initial_terminal->name = xstrdup ("initial_terminal");
|
||||
initial_terminal->kboard = initial_kboard;
|
||||
initial_terminal->delete_terminal_hook = &delete_initial_terminal;
|
||||
|
|
@ -725,6 +742,7 @@ or some time later. */);
|
|||
Vdelete_terminal_functions = Qnil;
|
||||
|
||||
DEFSYM (Qterminal_live_p, "terminal-live-p");
|
||||
DEFSYM (Qframe_initial_p, "frame-initial-p");
|
||||
DEFSYM (Qdelete_terminal_functions, "delete-terminal-functions");
|
||||
DEFSYM (Qrun_hook_with_args, "run-hook-with-args");
|
||||
|
||||
|
|
@ -734,6 +752,7 @@ or some time later. */);
|
|||
defsubr (&Sdelete_terminal);
|
||||
defsubr (&Sframe_terminal);
|
||||
defsubr (&Sterminal_live_p);
|
||||
defsubr (&Sframe_initial_p);
|
||||
defsubr (&Sterminal_list);
|
||||
defsubr (&Sterminal_name);
|
||||
defsubr (&Sterminal_parameters);
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ get_frame_dc (struct frame *f)
|
|||
HGDIOBJ obj;
|
||||
struct w32_output *output;
|
||||
|
||||
if (f->output_method != output_w32)
|
||||
if (!FRAME_W32_P (f))
|
||||
emacs_abort ();
|
||||
|
||||
enter_crit ();
|
||||
|
|
|
|||
33
src/xdisp.c
33
src/xdisp.c
|
|
@ -13665,7 +13665,7 @@ clear_garbaged_frames (void)
|
|||
selected frame, and might leave the selected
|
||||
frame with corrupted display, if it happens not
|
||||
to be marked garbaged. */
|
||||
&& !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
|
||||
&& !(f != sf && is_tty_frame (f)))
|
||||
redraw_frame (f);
|
||||
else
|
||||
clear_current_matrices (f);
|
||||
|
|
@ -16653,11 +16653,8 @@ hscroll_window_tree (Lisp_Object window)
|
|||
}
|
||||
}
|
||||
if (cursor_row->truncated_on_left_p)
|
||||
{
|
||||
/* On TTY frames, don't count the left truncation glyph. */
|
||||
struct frame *f = XFRAME (WINDOW_FRAME (w));
|
||||
x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
|
||||
}
|
||||
/* On TTY frames, don't count the left truncation glyph. */
|
||||
x_offset -= is_tty_frame (XFRAME (WINDOW_FRAME (w)));
|
||||
|
||||
text_area_width = window_box_width (w, TEXT_AREA);
|
||||
|
||||
|
|
@ -17391,7 +17388,7 @@ redisplay_internal (void)
|
|||
windows_or_buffers_changed = 47;
|
||||
|
||||
struct frame *previous_frame;
|
||||
if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
|
||||
if (is_tty_frame (sf)
|
||||
&& (previous_frame = FRAME_TTY (sf)->previous_frame,
|
||||
previous_frame != sf))
|
||||
{
|
||||
|
|
@ -17836,8 +17833,7 @@ redisplay_internal (void)
|
|||
}
|
||||
|
||||
retry_frame:
|
||||
if (FRAME_WINDOW_P (f)
|
||||
|| FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f) || f == sf)
|
||||
if (FRAME_WINDOW_P (f) || is_tty_frame (f) || f == sf)
|
||||
{
|
||||
/* Only GC scrollbars when we redisplay the whole frame. */
|
||||
bool gcscrollbars = f->redisplay || !REDISPLAY_SOME_P ();
|
||||
|
|
@ -32864,6 +32860,8 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
|
|||
/* Mirror for R2L. */
|
||||
if (direction == R2L)
|
||||
{
|
||||
face_id = GLYPH_CODE_FACE (gc);
|
||||
|
||||
/* Try bidi mirroring first. */
|
||||
int c = bidi_mirror_char (GLYPH_CODE_CHAR (gc));
|
||||
|
||||
|
|
@ -32877,16 +32875,23 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
|
|||
{
|
||||
c = XFIXNUM (val);
|
||||
|
||||
/* If something goes wrong defaults to '/'. */
|
||||
/* If something goes wrong, fall back to '/'. */
|
||||
if (CHAR_VALID_P (c))
|
||||
SET_GLYPH (glyph, c, face_id);
|
||||
else
|
||||
SET_GLYPH (glyph, '/', face_id);
|
||||
}
|
||||
else
|
||||
SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct face *face = FACE_FROM_ID (it->f, face_id);
|
||||
int id = FACE_FOR_CHAR (it->f, face, c, -1, Qnil);
|
||||
|
||||
/* Bidi mirroring. */
|
||||
SET_GLYPH (glyph, c, face_id);
|
||||
SET_GLYPH (glyph, c, id);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* No mirroring. */
|
||||
|
|
@ -32925,6 +32930,8 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
|
|||
if (((it->bidi_it.paragraph_dir == R2L) && !left_edge_p) ||
|
||||
((it->bidi_it.paragraph_dir == L2R) && left_edge_p))
|
||||
{
|
||||
face_id = GLYPH_CODE_FACE (gc);
|
||||
|
||||
/* Try bidi mirroring first. */
|
||||
int c = bidi_mirror_char (GLYPH_CODE_CHAR (gc));
|
||||
|
||||
|
|
@ -32938,12 +32945,14 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
|
|||
{
|
||||
c = XFIXNUM (val);
|
||||
|
||||
/* If something goes wrong defaults to '$'. */
|
||||
/* If something goes wrong, fall back to '$'. */
|
||||
if (CHAR_VALID_P (c))
|
||||
SET_GLYPH (glyph, c, face_id);
|
||||
else
|
||||
SET_GLYPH (glyph, '$', face_id);
|
||||
}
|
||||
else
|
||||
SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
10
src/xfaces.c
10
src/xfaces.c
|
|
@ -5827,7 +5827,7 @@ face for italic. */)
|
|||
}
|
||||
|
||||
/* Dispatch to the appropriate handler. */
|
||||
if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
|
||||
if (is_tty_frame (f))
|
||||
supports = tty_supports_face_attributes_p (f, attrs, def_face);
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
else
|
||||
|
|
@ -6121,7 +6121,7 @@ realize_default_face (struct frame *f)
|
|||
ASET (lface, LFACE_FOREGROUND_INDEX, XCDR (color));
|
||||
else if (FRAME_WINDOW_P (f))
|
||||
return false;
|
||||
else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
|
||||
else if (FRAME_INITIAL_P (f) || is_tty_frame (f))
|
||||
ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg));
|
||||
else
|
||||
emacs_abort ();
|
||||
|
|
@ -6136,7 +6136,7 @@ realize_default_face (struct frame *f)
|
|||
ASET (lface, LFACE_BACKGROUND_INDEX, XCDR (color));
|
||||
else if (FRAME_WINDOW_P (f))
|
||||
return false;
|
||||
else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
|
||||
else if (FRAME_INITIAL_P (f) || is_tty_frame (f))
|
||||
ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg));
|
||||
else
|
||||
emacs_abort ();
|
||||
|
|
@ -6247,7 +6247,7 @@ realize_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE],
|
|||
|
||||
if (FRAME_WINDOW_P (cache->f))
|
||||
face = realize_gui_face (cache, attrs);
|
||||
else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
|
||||
else if (is_tty_frame (cache->f))
|
||||
face = realize_tty_face (cache, attrs);
|
||||
else if (FRAME_INITIAL_P (cache->f))
|
||||
{
|
||||
|
|
@ -6760,7 +6760,7 @@ realize_tty_face (struct face_cache *cache,
|
|||
struct frame *f = cache->f;
|
||||
|
||||
/* Frame must be a termcap frame. */
|
||||
eassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
|
||||
eassert (is_tty_frame (cache->f));
|
||||
|
||||
/* Allocate a new realized face. */
|
||||
face = make_realized_face (attrs);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,10 @@ This function is intended to be set to `auth-source-debug'."
|
|||
((symbol-function 'auth-source-pass-entries) (lambda () (mapcar #'car ,store))))
|
||||
(let ((auth-source-debug #'auth-source-pass--debug)
|
||||
(auth-source-pass--debug-log nil)
|
||||
(auth-source-pass--parse-log nil))
|
||||
(auth-source-pass--parse-log nil)
|
||||
;; Any existing directory will do, since we shouldn't do I/O
|
||||
;; except for the guard in `auth-source-pass-search'.
|
||||
(auth-source-pass-filename default-directory))
|
||||
,@body)))
|
||||
|
||||
(defun auth-source-pass--explain-match-entry-p (entry hostname &optional user port)
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@
|
|||
(erase-buffer))
|
||||
(setopt cus-edit-test-foo1 :foo)
|
||||
(buffer-substring-no-properties (point-min) (point-max)))))
|
||||
(should (string-search "Value `:foo' for variable `cus-edit-test-foo1' does not match its type \"number\""
|
||||
(should (string-search "Value does not match cus-edit-test-foo1's type `number': :foo\n"
|
||||
warn-txt))))
|
||||
|
||||
(defcustom cus-edit-test-bug63290-option nil
|
||||
|
|
|
|||
|
|
@ -658,5 +658,155 @@ The current directory at call time should not affect the result (Bug#50630)."
|
|||
(let ((default-directory test-dir-other))
|
||||
(files-tests--insert-directory-shows-given-free test-dir)))))
|
||||
|
||||
(ert-deftest dired-test-filename-with-newline-1 () ; bug#79528, bug#80499
|
||||
"Test handling of file name with literal embedded newline."
|
||||
;; File names with embedded newlines are not allowed on MS-Windows and
|
||||
;; MS-DOS.
|
||||
(skip-when (memq system-type '(windows-nt ms-dos)))
|
||||
(with-current-buffer "*Messages*"
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)))
|
||||
(let* ((dired-auto-toggle-b-switch nil)
|
||||
(dir (ert-resource-file
|
||||
(file-name-as-directory "filename-with-newline")))
|
||||
(file (concat dir "filename\nwith newline"))
|
||||
(buf (progn (make-empty-file file t)
|
||||
(dired (file-name-directory file))))
|
||||
(warnbuf (get-buffer "*Warnings*")))
|
||||
(should (dired--filename-with-newline-p))
|
||||
(let ((beg (point)) ; beginning of file name
|
||||
(_ (dired-move-to-end-of-filename)))
|
||||
(should (search-backward "with newline")) ; literal space in file name
|
||||
(should (search-backward "\n" beg))) ; literal newline in file name
|
||||
(if noninteractive
|
||||
(with-current-buffer "*Messages*"
|
||||
(goto-char (point-min))
|
||||
(should (search-forward
|
||||
"Warning (dired): Literal newline in file name.")))
|
||||
(should (get-buffer-window warnbuf))
|
||||
(with-current-buffer warnbuf
|
||||
(goto-char (point-min))
|
||||
(should (string-match
|
||||
(regexp-quote "Warning (dired): Literal newline in file name.")
|
||||
(buffer-substring (pos-bol) (pos-eol))))))
|
||||
(kill-buffer buf)
|
||||
(kill-buffer warnbuf)
|
||||
(delete-directory dir t)))
|
||||
|
||||
(ert-deftest dired-test-filename-with-newline-2 () ; bug#79528, bug#80499
|
||||
"Test handling of file name with embedded newline using `b' switch."
|
||||
;; File names with embedded newlines are not allowed on MS-Windows and
|
||||
;; MS-DOS.
|
||||
(skip-when (memq system-type '(windows-nt ms-dos)))
|
||||
(with-current-buffer "*Messages*"
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)))
|
||||
(let* ((dired-auto-toggle-b-switch t)
|
||||
(dir (ert-resource-file
|
||||
(file-name-as-directory "filename-with-newline")))
|
||||
(file (concat dir "filename\nwith newline"))
|
||||
(buf (progn (make-empty-file file t)
|
||||
(dired-noselect (file-name-directory file))))
|
||||
(warnbuf (get-buffer "*Warnings*")))
|
||||
(with-current-buffer buf
|
||||
(should (dired--filename-with-newline-p))
|
||||
(dired--toggle-b-switch)
|
||||
(let ((beg (point)) ; beginning of file name
|
||||
(_ (dired-move-to-end-of-filename)))
|
||||
(should (search-backward "with\\ newline")) ; result of ls -b switch
|
||||
(should (search-backward "\\n" beg)))) ; result of ls -b switch
|
||||
(if noninteractive
|
||||
(with-current-buffer "*Messages*"
|
||||
(goto-char (point-min))
|
||||
(should-error (search-forward
|
||||
"Warning (dired): Literal newline in file name.")))
|
||||
(should-not (get-buffer "*Warnings*")))
|
||||
(kill-buffer buf)
|
||||
(kill-buffer warnbuf)
|
||||
(delete-directory dir t)))
|
||||
|
||||
(ert-deftest dired-test-ls-error-message () ; bug#80499
|
||||
"Test invoking `dired' on a nonexisting file.
|
||||
A buffer should pop up containing the error emitted by ls. The buffer
|
||||
visiting the nonexisting file should killed before `dired' returns,
|
||||
hence another buffer should be returned."
|
||||
(let* ((dir (ert-resource-file (file-name-as-directory "empty-dir")))
|
||||
(name (concat dir "bla"))
|
||||
;; Use PARENT = t in make-directory call to avoid failing if
|
||||
;; the directyory already exists for some reason.
|
||||
(buf (progn (make-directory dir t)
|
||||
(dired name))))
|
||||
;; This is for MS-Windows and MS-DOS in the default configuration.
|
||||
(when (and (featurep 'ls-lisp)
|
||||
(boundp 'ls-lisp-use-insert-directory-program)
|
||||
(null ls-lisp-use-insert-directory-program))
|
||||
(should (bufferp buf))
|
||||
(should (equal (buffer-name buf) (file-name-nondirectory name)))
|
||||
(with-current-buffer buf
|
||||
;; 'ls-lisp' creates a Dired buffer of just 3 lines, with
|
||||
;; "(No match)" on the last line
|
||||
(should (string-match "(No match)" (buffer-string)))
|
||||
(should (= 3 (line-number-at-pos (buffer-size) t)))))
|
||||
;; This is for Posix systems and for MS-Windows/DOS when they use 'ls'.
|
||||
(unless (and (featurep 'ls-lisp)
|
||||
(boundp 'ls-lisp-use-insert-directory-program)
|
||||
(null ls-lisp-use-insert-directory-program))
|
||||
(let ((errbuf (get-buffer "*ls error*")))
|
||||
(should (get-buffer-window errbuf))
|
||||
(should-not (equal (buffer-name buf) (file-name-nondirectory name)))
|
||||
(with-current-buffer errbuf
|
||||
(should (string-match-p
|
||||
(format
|
||||
;; Use .* around file name to account for different
|
||||
;; file-name quoting styles, or no quoting at all.
|
||||
"%s: cannot access .*%s.*: No such file or directory\n"
|
||||
insert-directory-program (file-name-nondirectory name))
|
||||
(buffer-string))))
|
||||
(kill-buffer errbuf))
|
||||
(delete-directory dir t))))
|
||||
|
||||
|
||||
(defun dired-test--filename-with-backslash-n ()
|
||||
"Core of test `dired-test-filename-with-backslash-n'."
|
||||
(let* ((dir (ert-resource-file
|
||||
(file-name-as-directory "filename-with-backslash")))
|
||||
(file (concat dir "C:\\nppdf32log\\debuglog.txt"))
|
||||
(buf (progn (make-empty-file file t)
|
||||
(dired-noselect (file-name-directory file))))
|
||||
(warnbuf (get-buffer "*Warnings*")))
|
||||
(with-current-buffer buf
|
||||
(should-not (dired--filename-with-newline-p))
|
||||
(dired--toggle-b-switch)
|
||||
(should-not (dired--filename-with-newline-p))
|
||||
(let ((fn (car (directory-files dir t
|
||||
directory-files-no-dot-files-regexp))))
|
||||
(should (equal fn file))))
|
||||
(if noninteractive
|
||||
(with-current-buffer "*Messages*"
|
||||
(goto-char (point-min))
|
||||
(should-error (search-forward
|
||||
"Warning (dired): Literal newline in file name.")))
|
||||
(should-not (get-buffer "*Warnings*")))
|
||||
(kill-buffer buf)
|
||||
(kill-buffer warnbuf)
|
||||
(delete-directory dir t)))
|
||||
|
||||
(ert-deftest dired-test-filename-with-backslash-n () ; bug#80608
|
||||
"Test file name containing literal backslash-n sequence.
|
||||
Dired should not treat this sequence as a newline character, regardless
|
||||
of the value of `dired-auto-toggle-b-switch'."
|
||||
;; File names with backslashes in basename are not allowed on MS systems.
|
||||
(skip-when (memq system-type '(windows-nt ms-dos)))
|
||||
(with-current-buffer "*Messages*"
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)))
|
||||
(let ((dired-auto-toggle-b-switch nil))
|
||||
(dired-test--filename-with-backslash-n))
|
||||
(with-current-buffer "*Messages*"
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)))
|
||||
(let ((dired-auto-toggle-b-switch nil))
|
||||
(dired-test--filename-with-backslash-n)))
|
||||
|
||||
(provide 'dired-tests)
|
||||
;;; dired-tests.el ends here
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue