Merge from origin/emacs-27
a4e4510ccd
Fix handling MS-Windows keyboard input above the BMPa38bebb0c1
* etc/NEWS: More complete description of rx 'not' changes.d373647e8f
; * doc/emacs/mini.texi (Yes or No Prompts): Fix last change.1ca6d15656
* doc/emacs/mini.texi (Yes or No Prompts): 'y-or-n-p' now ...fe1a447d52
Don't attempt to cache glyph metrics for FONT_INVALID_CODEb42b894d1d
Fix fit-frame-to-buffer for multi-monitor setup366fd4fd07
(emacs-27) ; * etc/NEWS: Fix typo.49d3cd90bd
rx: Improve 'or' compositionality (bug#37659)6b48aedb6b
* lisp/tab-line.el: Fix auto-hscrolling (bug#39649)c5f255d681
(tag: emacs-27.0.90) ; Update lisp/ldefs-boot.el60c84ad992
; * etc/TODO: Fix last change.5af9e5baad
; Add an entry to TODOd424195905
Fix rx charset generation9908b5a614
Merge branch 'emacs-27' of git.savannah.gnu.org:/srv/git/e...6dc2ebe00e
Fix overquoting in mule.el5cca73dd82
* src/timefns.c (time_arith): Omit incorrect comment.d767c357ca
Merge branch 'emacs-27' of git.savannah.gnu.org:/srv/git/e...4dec693f70
* lisp/vc/vc-cvs.el (vc-cvs-ignore): Copy-edit doc stringff729e3f97
; bug#39779: Fix some typos in documentation.696ee02c3a
checkdoc: Don't mistake "cf." for sentence end # Conflicts: # etc/NEWS
This commit is contained in:
commit
6a0e1c4104
23 changed files with 291 additions and 115 deletions
|
@ -813,35 +813,23 @@ varieties.
|
|||
|
||||
@cindex y or n prompt
|
||||
For the first type of yes-or-no query, the prompt ends with
|
||||
@samp{(y or n)}. Such a query does not actually use the minibuffer;
|
||||
the prompt appears in the echo area, and you answer by typing either
|
||||
@samp{y} or @samp{n}, which immediately delivers the response. For
|
||||
example, if you type @kbd{C-x C-w} (@kbd{write-file}) to save a
|
||||
buffer, and enter the name of an existing file, Emacs issues a prompt
|
||||
like this:
|
||||
@w{@samp{(y or n)}}. You answer the query by typing a single key,
|
||||
either @samp{y} or @samp{n}, which immediately exits the minibuffer
|
||||
and delivers the response. For example, if you type @kbd{C-x C-w}
|
||||
(@kbd{write-file}) to save a buffer, and enter the name of an existing
|
||||
file, Emacs issues a prompt like this:
|
||||
|
||||
@smallexample
|
||||
File ‘foo.el’ exists; overwrite? (y or n)
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
Because this query does not actually use the minibuffer, the usual
|
||||
minibuffer editing commands cannot be used. However, you can perform
|
||||
some window scrolling operations while the query is active: @kbd{C-l}
|
||||
recenters the selected window; @kbd{C-v} (or @key{PageDown}, or
|
||||
@key{next}) scrolls forward; @kbd{M-v} (or @key{PageUp}, or
|
||||
@key{prior}) scrolls backward; @kbd{C-M-v} scrolls forward in the next
|
||||
window; and @kbd{C-M-S-v} scrolls backward in the next window. Typing
|
||||
@kbd{C-g} dismisses the query, and quits the command that issued it
|
||||
(@pxref{Quitting}).
|
||||
|
||||
@cindex yes or no prompt
|
||||
The second type of yes-or-no query is typically employed if
|
||||
giving the wrong answer would have serious consequences; it uses the
|
||||
minibuffer, and features a prompt ending with @samp{(yes or no)}. For
|
||||
example, if you invoke @kbd{C-x k} (@code{kill-buffer}) on a
|
||||
file-visiting buffer with unsaved changes, Emacs activates the
|
||||
minibuffer with a prompt like this:
|
||||
The second type of yes-or-no query is typically employed if giving
|
||||
the wrong answer would have serious consequences; it thus features a
|
||||
longer prompt ending with @samp{(yes or no)}. For example, if you
|
||||
invoke @kbd{C-x k} (@code{kill-buffer}) on a file-visiting buffer with
|
||||
unsaved changes, Emacs activates the minibuffer with a prompt like
|
||||
this:
|
||||
|
||||
@smallexample
|
||||
Buffer foo.el modified; kill anyway? (yes or no)
|
||||
|
@ -849,7 +837,12 @@ Buffer foo.el modified; kill anyway? (yes or no)
|
|||
|
||||
@noindent
|
||||
To answer, you must type @samp{yes} or @samp{no} into the minibuffer,
|
||||
followed by @key{RET}. The minibuffer behaves as described in the
|
||||
previous sections; you can switch to another window with @kbd{C-x o},
|
||||
use the history commands @kbd{M-p} and @kbd{M-n}, etc. Type @kbd{C-g}
|
||||
to quit the minibuffer and the querying command.
|
||||
followed by @key{RET}.
|
||||
|
||||
With both types of yes-or-no query the minibuffer behaves as described
|
||||
in the previous sections; you can recenter the selected window with
|
||||
@kbd{C-l}, scroll that window (@kbd{C-v} or @kbd{PageDown} scrolls
|
||||
forward, @kbd{M-v} or @kbd{PageUp} scrolls backward), switch to
|
||||
another window with @kbd{C-x o}, use the history commands @kbd{M-p}
|
||||
and @kbd{M-n}, etc. Type @kbd{C-g} to dismiss the query, and quit the
|
||||
minibuffer and the querying command (@pxref{Quitting}).
|
||||
|
|
|
@ -3264,7 +3264,7 @@ that deletion fails for whatever reason, the child frame is made a
|
|||
top-level frame.
|
||||
|
||||
Whether a child frame can have a menu or tool bar is window-system or
|
||||
window manager dependent. Most window-systems explicitly disallow menus
|
||||
window manager dependent. Most window-systems explicitly disallow menu
|
||||
bars for child frames. It seems advisable to disable both, menu and
|
||||
tool bars, via the frame's initial parameters settings.
|
||||
|
||||
|
|
|
@ -1086,8 +1086,9 @@ Corresponding string regexp: @samp{@var{A}@var{B}@dots{}}
|
|||
@itemx @code{(| @var{rx}@dots{})}
|
||||
@cindex @code{|} in rx
|
||||
Match exactly one of the @var{rx}s.
|
||||
If all arguments are string literals, the longest possible match
|
||||
will always be used. Otherwise, either the longest match or the
|
||||
If all arguments are strings, characters, or @code{or} forms
|
||||
so constrained, the longest possible match will always be used.
|
||||
Otherwise, either the longest match or the
|
||||
first (in left-to-right order) will be used.
|
||||
Without arguments, the expression will not match anything at all.@*
|
||||
Corresponding string regexp: @samp{@var{A}\|@var{B}\|@dots{}}.
|
||||
|
|
|
@ -1076,7 +1076,7 @@ package is only activated if all its dependencies have been).
|
|||
Its format is a list of lists on a single line. The @code{car} of
|
||||
each sub-list is the name of a package, as a symbol. The @code{cadr}
|
||||
of each sub-list is the minimum acceptable version number, as a string
|
||||
that can be parse by @code{version-to-list}. An entry that lacks a
|
||||
that can be parsed by @code{version-to-list}. An entry that lacks a
|
||||
version (i.e., an entry which is just a symbol, or a sub-list of one
|
||||
element) is equivalent to entry with version "0". For instance:
|
||||
|
||||
|
|
|
@ -858,7 +858,7 @@ is a buffer if the buffer-local value of the variable is being
|
|||
changed, @code{nil} otherwise.
|
||||
@end defun
|
||||
|
||||
@defun remove-variable-watch symbol watch-function
|
||||
@defun remove-variable-watcher symbol watch-function
|
||||
This function removes @var{watch-function} from @var{symbol}'s list of
|
||||
watchers.
|
||||
@end defun
|
||||
|
|
|
@ -3181,7 +3181,7 @@ For example:
|
|||
(broken-reply-to . t))))
|
||||
@end lisp
|
||||
|
||||
All clauses that matches the group name will be used, but the last
|
||||
All clauses that match the group name will be used, but the last
|
||||
setting ``wins''. So if you have two clauses that both match the
|
||||
group name, and both set, say @code{display}, the last setting will
|
||||
override the first.
|
||||
|
@ -17874,7 +17874,7 @@ presence of 7 special headers. These headers are of the form
|
|||
@code{X-Diary-<something>}, @code{<something>} being one of
|
||||
@code{Minute}, @code{Hour}, @code{Dom}, @code{Month}, @code{Year},
|
||||
@code{Time-Zone} and @code{Dow}. @code{Dom} means ``Day of Month'', and
|
||||
@code{dow} means ``Day of Week''. These headers actually behave like
|
||||
@code{Dow} means ``Day of Week''. These headers actually behave like
|
||||
crontab specifications and define the event date(s):
|
||||
|
||||
@itemize @bullet
|
||||
|
@ -30916,7 +30916,7 @@ description = <string>
|
|||
|
||||
Believe it or not, but some people who use Gnus haven't really used
|
||||
Emacs much before they embarked on their journey on the Gnus Love Boat.
|
||||
If you are one of those unfortunates whom ``@kbd{C-M-a}'', ``kill the
|
||||
If you are one of those unfortunates to whom ``@kbd{C-M-a}'', ``kill the
|
||||
region'', and ``set @code{gnus-flargblossen} to an alist where the key
|
||||
is a regexp that is used for matching on the group name'' are magical
|
||||
phrases with little or no meaning, then this appendix is for you. If
|
||||
|
|
|
@ -739,9 +739,9 @@ stepping, you will see where the loop starts and ends. Also, examine
|
|||
the data being used in the loop and try to determine why the loop does
|
||||
not exit when it should.
|
||||
|
||||
On GNU and Unix systems, you can also trying sending Emacs SIGUSR2,
|
||||
On GNU and Unix systems, you can also try sending Emacs SIGUSR2,
|
||||
which, if 'debug-on-event' has its default value, will cause Emacs to
|
||||
attempt to break it out of its current loop and into the Lisp
|
||||
attempt to break out of its current loop and enter the Lisp
|
||||
debugger. (See the node "Debugging" in the ELisp manual for the
|
||||
details about the Lisp debugger.) This feature is useful when a
|
||||
C-level debugger is not conveniently available.
|
||||
|
|
11
etc/NEWS.27
11
etc/NEWS.27
|
@ -2323,7 +2323,16 @@ With 'or' and 'not', it can be used to compose character-matching
|
|||
expressions from simpler parts.
|
||||
|
||||
+++
|
||||
*** 'not' argument can now be a character or single-char string.
|
||||
*** 'not' now accepts more argument types.
|
||||
The argument can now also be a character, a single-character string,
|
||||
an 'intersection' form, or an 'or' form whose arguments each match a
|
||||
single character.
|
||||
|
||||
+++
|
||||
*** Nested 'or' forms of strings guarantee a longest match.
|
||||
For example, '(or (or "IN" "OUT") (or "INPUT" "OUTPUT"))' now matches
|
||||
the whole string "INPUT" if present, not just "IN". Previously, this
|
||||
was only guaranteed inside a single 'or' form of string literals.
|
||||
|
||||
** Frames
|
||||
|
||||
|
|
71
etc/TODO
71
etc/TODO
|
@ -244,6 +244,23 @@ populate composition-function-table with those rules. See
|
|||
composite.el for examples of this, and also grep lisp/language/*.el
|
||||
for references to composition-function-table.
|
||||
|
||||
One problem with character compositions that will need to be solved is
|
||||
that composition-function-table, the char-table which holds the
|
||||
composition rules, is a global variable, whereas use of ligatures is
|
||||
inherently specific to buffer-local stuff like the major mode and the
|
||||
script or language in use. So there should be a buffer-local variable
|
||||
to augment/customize/override the global composition rules.
|
||||
|
||||
Another problem is that ligatures are frequently composed of ASCII
|
||||
characters, and some of those ASCII characters are present in the mode
|
||||
line, for example "--". Since displaying a ligature instead of 2
|
||||
separate '-' characters on a mode line is not right, there should be a
|
||||
way of preventing the ligation from happening. One possibility is to
|
||||
have a ZWNJ character separate these ASCII characters; another
|
||||
possibility is to introduce a special text property that prevents
|
||||
character composition, and place that property on the relevant parts
|
||||
of the mode line.
|
||||
|
||||
The prettify-symbols-mode should be deprecated once ligature support
|
||||
is in place.
|
||||
|
||||
|
@ -267,6 +284,60 @@ should invoke the 'shape' method. 'hbfont_shape' should be extended
|
|||
to pass to 'hb_shape_full' the required array of features, as
|
||||
mentioned in the above HarfBuzz discussion.
|
||||
|
||||
** Better support for displaying Emoji
|
||||
|
||||
Emacs is capable of displaying Emoji and some of the Emoji sequences,
|
||||
provided that its fontsets are configured with a suitable font. To
|
||||
make this easier out of the box, the following should be done:
|
||||
|
||||
*** Populate composition-function-table with Emoji rules
|
||||
|
||||
The Unicode Character Database (UCD) includes several data files that
|
||||
define the valid Emoji sequences. These files should be imported into
|
||||
the Emacs tree, and should be converted by some script at Emacs build
|
||||
time to Lisp code that populates composition-function-table with the
|
||||
corresponding composition rules.
|
||||
|
||||
*** Augment the default fontsets with Emoji-capable fonts
|
||||
|
||||
The default fontsets set up by fontest.el should include known free
|
||||
fonts that provide good support for displaying Emoji sequences. In
|
||||
addition, the rule that the default face's font is used for symbol and
|
||||
punctuation characters, disregarding the fontsets, should be modified
|
||||
to exempt Emoji from this rule (since Emoji characters belong to the
|
||||
'symbol' script in Emacs), so that use-default-font-for-symbols would
|
||||
not have to be tweaked to have Emoji display by default with a capable
|
||||
font.
|
||||
|
||||
*** Consider changing the default display of Variation Selectors
|
||||
|
||||
Emacs by default displays the Variation Selector (VS) codepoints not
|
||||
composed with base characters as hex codes in a box. The Unicode FAQ
|
||||
says that if variation sequences cannot be supported, the VS
|
||||
characters should not be shown, leaving just the base character of the
|
||||
sequence visible. This could be handled via glyphless-char-display,
|
||||
by changing the entries for VS codepoints to 'zero-width'. Or we
|
||||
could display them as a thin 1-pixel space, as we do with format
|
||||
control characters, by using 'thin-space' there.
|
||||
|
||||
*** Special face for displaying text presentation of Emoji
|
||||
|
||||
Emoji-capable fonts support Emoji sequences with the U+FE0F VARIATION
|
||||
SELECTOR-16 (VS16) for emoji-style display, but usually don't support
|
||||
the U+FE0F VARIATION SELECTOR-15 (VS15) for text-style display. There
|
||||
are other fonts which support the text-style sequences, but not
|
||||
emoji-style. Since Emacs selects a font based on a single character,
|
||||
it cannot choose 2 different fonts for displaying both styles of the
|
||||
same base character. To display both styles in the same buffer, one
|
||||
could use a special face, placing a 'face' text property on portions
|
||||
of the text. This special face could specify a specific font known to
|
||||
support text-style Emoji sequences. Emacs could have such a face
|
||||
built-in.
|
||||
|
||||
See the discussion of bug#39799 for more details about this task.
|
||||
Another relevant resource is the Unicode Technical Standard #51
|
||||
"Unicode Emoji" (http://www.unicode.org/reports/tr51/).
|
||||
|
||||
** Extend text-properties and overlays
|
||||
*** Several text-property planes
|
||||
This would get us rid of font-lock-face property (and I'd be happy to
|
||||
|
|
|
@ -2073,7 +2073,7 @@ If the offending word is in a piece of quoted text, then it is skipped."
|
|||
;; piece of an abbreviation
|
||||
;; FIXME etc
|
||||
(looking-at
|
||||
"\\([a-zA-Z]\\|[iI]\\.?e\\|[eE]\\.?g\\)\\."))
|
||||
"\\([a-zA-Z]\\|[iI]\\.?e\\|[eE]\\.?g\\|[cC]f\\)\\."))
|
||||
(error t))))
|
||||
(if (checkdoc-autofix-ask-replace
|
||||
b e
|
||||
|
|
|
@ -254,22 +254,39 @@ Left-fold the list L, starting with X, by the binary function F."
|
|||
(setq l (cdr l)))
|
||||
x)
|
||||
|
||||
(defun rx--normalise-or-arg (form)
|
||||
"Normalise the `or' argument FORM.
|
||||
Characters become strings, user-definitions and `eval' forms are expanded,
|
||||
and `or' forms are normalised recursively."
|
||||
(cond ((characterp form)
|
||||
(char-to-string form))
|
||||
((and (consp form) (memq (car form) '(or |)))
|
||||
(cons (car form) (mapcar #'rx--normalise-or-arg (cdr form))))
|
||||
((and (consp form) (eq (car form) 'eval))
|
||||
(rx--normalise-or-arg (rx--expand-eval (cdr form))))
|
||||
(t
|
||||
(let ((expanded (rx--expand-def form)))
|
||||
(if expanded
|
||||
(rx--normalise-or-arg expanded)
|
||||
form)))))
|
||||
|
||||
(defun rx--all-string-or-args (body)
|
||||
"If BODY only consists of strings or such `or' forms, return all the strings.
|
||||
Otherwise throw `rx--nonstring'."
|
||||
(mapcan (lambda (form)
|
||||
(cond ((stringp form) (list form))
|
||||
((and (consp form) (memq (car form) '(or |)))
|
||||
(rx--all-string-or-args (cdr form)))
|
||||
(t (throw 'rx--nonstring nil))))
|
||||
body))
|
||||
|
||||
(defun rx--translate-or (body)
|
||||
"Translate an or-pattern of zero or more rx items.
|
||||
Return (REGEXP . PRECEDENCE)."
|
||||
;; FIXME: Possible improvements:
|
||||
;;
|
||||
;; - Turn single characters to strings: (or ?a ?b) -> (or "a" "b"),
|
||||
;; so that they can be candidates for regexp-opt.
|
||||
;;
|
||||
;; - Translate compile-time strings (`eval' forms), again for regexp-opt.
|
||||
;;
|
||||
;; - Flatten sub-patterns first: (or (or A B) (or C D)) -> (or A B C D)
|
||||
;; in order to improve effectiveness of regexp-opt.
|
||||
;; This would also help composability.
|
||||
;;
|
||||
;; - Use associativity to run regexp-opt on contiguous subsets of arguments
|
||||
;; if not all of them are strings. Example:
|
||||
;; Then call regexp-opt on runs of string arguments. Example:
|
||||
;; (or (+ digit) "CHARLIE" "CHAN" (+ blank))
|
||||
;; -> (or (+ digit) (or "CHARLIE" "CHAN") (+ blank))
|
||||
;;
|
||||
|
@ -279,33 +296,32 @@ Return (REGEXP . PRECEDENCE)."
|
|||
;; so that (or "@" "%" digit (any "A-Z" space) (syntax word))
|
||||
;; -> (any "@" "%" digit "A-Z" space word)
|
||||
;; -> "[A-Z@%[:digit:][:space:][:word:]]"
|
||||
;;
|
||||
;; Problem: If a subpattern is carefully written to be
|
||||
;; optimizable by regexp-opt, how do we prevent the transforms
|
||||
;; above from destroying that property?
|
||||
;; Example: (or "a" (or "abc" "abd" "abe"))
|
||||
(cond
|
||||
((null body) ; No items: a never-matching regexp.
|
||||
(rx--empty))
|
||||
((null (cdr body)) ; Single item.
|
||||
(rx--translate (car body)))
|
||||
((rx--every #'stringp body) ; All strings.
|
||||
(cons (list (regexp-opt body nil))
|
||||
t))
|
||||
((rx--every #'rx--charset-p body) ; All charsets.
|
||||
(rx--translate-union nil body))
|
||||
(t
|
||||
(cons (append (car (rx--translate (car body)))
|
||||
(mapcan (lambda (item)
|
||||
(cons "\\|" (car (rx--translate item))))
|
||||
(cdr body)))
|
||||
nil))))
|
||||
(let* ((args (mapcar #'rx--normalise-or-arg body))
|
||||
(all-strings (catch 'rx--nonstring (rx--all-string-or-args args))))
|
||||
(cond
|
||||
(all-strings ; Only strings.
|
||||
(cons (list (regexp-opt all-strings nil))
|
||||
t))
|
||||
((rx--every #'rx--charset-p args) ; All charsets.
|
||||
(rx--translate-union nil args))
|
||||
(t
|
||||
(cons (append (car (rx--translate (car args)))
|
||||
(mapcan (lambda (item)
|
||||
(cons "\\|" (car (rx--translate item))))
|
||||
(cdr args)))
|
||||
nil)))))))
|
||||
|
||||
(defun rx--charset-p (form)
|
||||
"Whether FORM looks like a charset, only consisting of character intervals
|
||||
and set operations."
|
||||
(or (and (consp form)
|
||||
(or (and (memq (car form) '(any 'in 'char))
|
||||
(or (and (memq (car form) '(any in char))
|
||||
(rx--every (lambda (x) (not (symbolp x))) (cdr form)))
|
||||
(and (memq (car form) '(not or | intersection))
|
||||
(rx--every #'rx--charset-p (cdr form)))))
|
||||
|
@ -450,6 +466,10 @@ classes."
|
|||
(not negated))
|
||||
(cons (list (regexp-quote (char-to-string (caar items))))
|
||||
t))
|
||||
;; Negated newline.
|
||||
((and (equal items '((?\n . ?\n)))
|
||||
negated)
|
||||
(rx--translate-symbol 'nonl))
|
||||
;; At least one character or class, possibly negated.
|
||||
(t
|
||||
(cons
|
||||
|
@ -836,11 +856,15 @@ Return (REGEXP . PRECEDENCE)."
|
|||
(cons (list (list 'regexp-quote arg)) 'seq))
|
||||
(t (error "rx `literal' form with non-string argument")))))
|
||||
|
||||
(defun rx--translate-eval (body)
|
||||
"Translate the `eval' form. Return (REGEXP . PRECEDENCE)."
|
||||
(defun rx--expand-eval (body)
|
||||
"Expand `eval' arguments. Return a new rx form."
|
||||
(unless (and body (null (cdr body)))
|
||||
(error "rx `eval' form takes exactly one argument"))
|
||||
(rx--translate (eval (car body))))
|
||||
(eval (car body)))
|
||||
|
||||
(defun rx--translate-eval (body)
|
||||
"Translate the `eval' form. Return (REGEXP . PRECEDENCE)."
|
||||
(rx--translate (rx--expand-eval body)))
|
||||
|
||||
(defvar rx--regexp-atomic-regexp nil)
|
||||
|
||||
|
|
|
@ -7774,11 +7774,11 @@ also be Lisp expression evaluating to a string),
|
|||
BUTTON: is the number of the regexp grouping actually matching the button,
|
||||
FORM: is a Lisp expression which must eval to true for the button to
|
||||
be added,
|
||||
CALLBACK: is the function to call when the user push this button, and each
|
||||
CALLBACK: is the function to call when the user pushes this button, and each
|
||||
PAR: is a number of a regexp grouping whose text will be passed to CALLBACK.
|
||||
|
||||
CALLBACK can also be a variable, in that case the value of that
|
||||
variable it the real callback function."
|
||||
CALLBACK can also be a variable, in which case the value of that
|
||||
variable is the real callback function."
|
||||
:group 'gnus-article-buttons
|
||||
:type '(repeat (list (choice regexp variable sexp)
|
||||
(integer :tag "Button")
|
||||
|
|
|
@ -174,7 +174,7 @@ no effect when spam-stat is invoked through spam.el."
|
|||
|
||||
(defcustom spam-stat-score-buffer-user-functions nil
|
||||
"List of additional scoring functions.
|
||||
Called one by one on the buffer.
|
||||
Called one by one on the buffer.
|
||||
|
||||
If all of these functions return non-nil answers, these numerical
|
||||
answers are added to the computed spam stat score on the buffer. If
|
||||
|
|
|
@ -2601,7 +2601,7 @@ This function is intended to be added to `auto-coding-functions'."
|
|||
(detect-coding-region (point-min) size t)))))
|
||||
;; Pure ASCII always comes back as undecided.
|
||||
(if (memq detected
|
||||
'(utf-8 'utf-8-with-signature 'utf-8-hfs undecided))
|
||||
'(utf-8 utf-8-with-signature utf-8-hfs undecided))
|
||||
'utf-8
|
||||
(warn "File contents detected as %s.
|
||||
Consider adding an encoding attribute to the xml declaration,
|
||||
|
|
|
@ -446,17 +446,19 @@ variable `tab-line-tabs-function'."
|
|||
(setq hscroll nil)
|
||||
(set-window-parameter nil 'tab-line-hscroll hscroll))
|
||||
(list separator
|
||||
(when (and (integerp hscroll) (not (zerop hscroll)))
|
||||
(when (and (numberp hscroll) (not (zerop hscroll)))
|
||||
tab-line-left-button)
|
||||
(when (if (integerp hscroll)
|
||||
(< (abs hscroll) (1- (length strings)))
|
||||
(when (if (numberp hscroll)
|
||||
(< (truncate hscroll) (1- (length strings)))
|
||||
(> (length strings) 1))
|
||||
tab-line-right-button)))
|
||||
(if hscroll (nthcdr (abs hscroll) strings) strings)
|
||||
(if hscroll (nthcdr (truncate hscroll) strings) strings)
|
||||
(when (eq tab-line-tabs-function #'tab-line-tabs-window-buffers)
|
||||
(list (concat separator (when tab-line-new-tab-choice
|
||||
tab-line-new-button)))))))
|
||||
|
||||
(defvar tab-line-auto-hscroll)
|
||||
|
||||
(defun tab-line-format ()
|
||||
"Template for displaying tab line for selected window."
|
||||
(let* ((tabs (funcall tab-line-tabs-function))
|
||||
|
@ -464,6 +466,13 @@ variable `tab-line-tabs-function'."
|
|||
(window-buffer)
|
||||
(window-parameter nil 'tab-line-hscroll)))
|
||||
(cache (window-parameter nil 'tab-line-cache)))
|
||||
;; Enable auto-hscroll again after it was disabled on manual scrolling.
|
||||
;; The moment to enable it is when the window-buffer was updated.
|
||||
(when (and tab-line-auto-hscroll ; if auto-hscroll was enabled
|
||||
(integerp (nth 2 cache-key)) ; integer on manual scroll
|
||||
cache ; window-buffer was updated
|
||||
(not (equal (nth 1 (car cache)) (nth 1 cache-key))))
|
||||
(set-window-parameter nil 'tab-line-hscroll (float (nth 2 cache-key))))
|
||||
(or (and cache (equal (car cache) cache-key) (cdr cache))
|
||||
(cdr (set-window-parameter
|
||||
nil 'tab-line-cache
|
||||
|
@ -478,24 +487,27 @@ the selected tab visible."
|
|||
:group 'tab-line
|
||||
:version "27.1")
|
||||
|
||||
(defvar tab-line-auto-hscroll-buffer (generate-new-buffer " *tab-line-hscroll*"))
|
||||
|
||||
(defun tab-line-auto-hscroll (strings hscroll)
|
||||
(with-temp-buffer
|
||||
(with-current-buffer tab-line-auto-hscroll-buffer
|
||||
(let ((truncate-partial-width-windows nil)
|
||||
(inhibit-modification-hooks t)
|
||||
show-arrows)
|
||||
(setq truncate-lines nil)
|
||||
(erase-buffer)
|
||||
(apply 'insert strings)
|
||||
(goto-char (point-min))
|
||||
(add-face-text-property (point-min) (point-max) 'tab-line)
|
||||
;; Continuation means tab-line doesn't fit completely,
|
||||
;; thus scroll arrows are needed for scrolling.
|
||||
(setq show-arrows (> (vertical-motion 1) 0))
|
||||
;; Try to auto-scroll only when scrolling is needed,
|
||||
;; Try to auto-hscroll only when scrolling is needed,
|
||||
;; but no manual scrolling was performed before.
|
||||
(when (and tab-line-auto-hscroll
|
||||
show-arrows
|
||||
;; Do nothing when scrolled manually
|
||||
(not (and (integerp hscroll) (>= hscroll 0))))
|
||||
(not (integerp hscroll)))
|
||||
(let ((selected (seq-position strings 'selected
|
||||
(lambda (str prop)
|
||||
(get-pos-property 1 prop str)))))
|
||||
|
@ -503,7 +515,7 @@ the selected tab visible."
|
|||
((null selected)
|
||||
;; Do nothing if no tab is selected
|
||||
)
|
||||
((or (not (integerp hscroll)) (< selected (abs hscroll)))
|
||||
((or (not (numberp hscroll)) (< selected (truncate hscroll)))
|
||||
;; Selected is scrolled to the left, or no scrolling yet
|
||||
(erase-buffer)
|
||||
(apply 'insert (reverse (seq-subseq strings 0 (1+ selected))))
|
||||
|
@ -520,14 +532,14 @@ the selected tab visible."
|
|||
(lambda (str tab)
|
||||
(eq (get-pos-property 1 'tab str) tab))))))
|
||||
(when new-hscroll
|
||||
(setq hscroll (- new-hscroll))
|
||||
(setq hscroll (float new-hscroll))
|
||||
(set-window-parameter nil 'tab-line-hscroll hscroll)))
|
||||
(setq hscroll nil)
|
||||
(set-window-parameter nil 'tab-line-hscroll hscroll)))
|
||||
(t
|
||||
;; Check if the selected tab is already visible
|
||||
(erase-buffer)
|
||||
(apply 'insert (seq-subseq strings (abs hscroll) (1+ selected)))
|
||||
(apply 'insert (seq-subseq strings (truncate hscroll) (1+ selected)))
|
||||
(goto-char (point-min))
|
||||
(add-face-text-property (point-min) (point-max) 'tab-line)
|
||||
(when (> (vertical-motion 1) 0)
|
||||
|
@ -547,7 +559,7 @@ the selected tab visible."
|
|||
(lambda (str tab)
|
||||
(eq (get-pos-property 1 'tab str) tab))))))
|
||||
(when new-hscroll
|
||||
(setq hscroll (- new-hscroll))
|
||||
(setq hscroll (float new-hscroll))
|
||||
(set-window-parameter nil 'tab-line-hscroll hscroll)))))))))
|
||||
(list show-arrows hscroll))))
|
||||
|
||||
|
@ -559,7 +571,7 @@ the selected tab visible."
|
|||
(funcall tab-line-tabs-function))))
|
||||
(set-window-parameter
|
||||
window 'tab-line-hscroll
|
||||
(max 0 (min (+ (if (integerp hscroll) (abs hscroll) 0) (or arg 1))
|
||||
(max 0 (min (+ (if (numberp hscroll) (truncate hscroll) 0) (or arg 1))
|
||||
(1- (length tabs)))))
|
||||
(when window
|
||||
(force-mode-line-update t))))
|
||||
|
|
|
@ -1222,23 +1222,24 @@ is non-nil."
|
|||
|
||||
(defun vc-cvs-ignore (file &optional directory _remove)
|
||||
"Ignore FILE under CVS.
|
||||
FILE is either absolute or relative to DIRECTORY. The basename
|
||||
of FILE is written unmodified into the ignore file and is
|
||||
FILE is either absolute or relative to DIRECTORY. The non-directory
|
||||
part of FILE is written unmodified into the ignore file and is
|
||||
therefore evaluated by CVS as an ignore pattern which follows
|
||||
glob(7) syntax. If the pattern should match any of the special
|
||||
characters ‘?*[\\\’ literally, they must be escaped with a
|
||||
characters `?*[\\' literally, they must be escaped with a
|
||||
backslash.
|
||||
|
||||
CVS processes one ignore file for each subdirectory. Patterns
|
||||
are separated by whitespace and only match files in the same
|
||||
directory. Since FILE can be a relative filename with leading
|
||||
diretories, FILE is expanded against DIRECTORY to determine the
|
||||
correct absolute filename. The directory name of this path is
|
||||
then used to determine the location of the ignore file. The base
|
||||
name of this path is used as pattern for the ignore file.
|
||||
directories, FILE is expanded against DIRECTORY to determine the
|
||||
correct absolute filename. The directory part of the resulting name
|
||||
is then used to determine the location of the ignore file. The
|
||||
non-directory part of the name is used as pattern for the ignore file.
|
||||
|
||||
Since patterns are whitespace sparated, it is usually better to
|
||||
replace spaces in filenames with question marks ‘?’."
|
||||
Since patterns are whitespace-separated, filenames containing spaces
|
||||
cannot be represented directly. A work-around is to replace such
|
||||
spaces with question marks."
|
||||
(setq file (directory-file-name (expand-file-name file directory)))
|
||||
(vc-cvs-append-to-ignore (file-name-directory file) (file-name-nondirectory file)))
|
||||
|
||||
|
|
|
@ -8806,8 +8806,7 @@ parameters of FRAME."
|
|||
(parent (frame-parent frame))
|
||||
(monitor-attributes
|
||||
(unless parent
|
||||
(car (display-monitor-attributes-list
|
||||
(frame-parameter frame 'display)))))
|
||||
(frame-monitor-attributes frame)))
|
||||
;; FRAME'S parent or display sizes. Used in connection
|
||||
;; with margins.
|
||||
(geometry
|
||||
|
@ -8816,11 +8815,11 @@ parameters of FRAME."
|
|||
(parent-or-display-width
|
||||
(if parent
|
||||
(frame-native-width parent)
|
||||
(- (nth 2 geometry) (nth 0 geometry))))
|
||||
(nth 2 geometry)))
|
||||
(parent-or-display-height
|
||||
(if parent
|
||||
(frame-native-height parent)
|
||||
(- (nth 3 geometry) (nth 1 geometry))))
|
||||
(nth 3 geometry)))
|
||||
;; FRAME's parent or workarea sizes. Used when no margins
|
||||
;; are specified.
|
||||
(parent-or-workarea
|
||||
|
@ -8882,13 +8881,15 @@ parameters of FRAME."
|
|||
(window--sanitize-margin
|
||||
(nth 2 margins) left-margin
|
||||
parent-or-display-width))
|
||||
(nth 2 parent-or-workarea)))
|
||||
(+ (nth 0 parent-or-workarea)
|
||||
(nth 2 parent-or-workarea))))
|
||||
(bottom-margin (if (nth 3 margins)
|
||||
(- parent-or-display-height
|
||||
(window--sanitize-margin
|
||||
(nth 3 margins) top-margin
|
||||
parent-or-display-height))
|
||||
(nth 3 parent-or-workarea)))
|
||||
(+ (nth 1 parent-or-workarea)
|
||||
(nth 3 parent-or-workarea))))
|
||||
;; Minimum and maximum sizes specified for FRAME.
|
||||
(sizes (or (frame-parameter frame 'fit-frame-to-buffer-sizes)
|
||||
fit-frame-to-buffer-sizes))
|
||||
|
|
|
@ -818,6 +818,11 @@ fill_gstring_body (Lisp_Object gstring)
|
|||
Lisp_Object header = AREF (gstring, 0);
|
||||
ptrdiff_t len = LGSTRING_CHAR_LEN (gstring);
|
||||
ptrdiff_t i;
|
||||
struct font *font = NULL;
|
||||
unsigned int code;
|
||||
|
||||
if (FONT_OBJECT_P (font_object))
|
||||
font = XFONT_OBJECT (font_object);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
|
@ -832,10 +837,15 @@ fill_gstring_body (Lisp_Object gstring)
|
|||
LGLYPH_SET_FROM (g, i);
|
||||
LGLYPH_SET_TO (g, i);
|
||||
LGLYPH_SET_CHAR (g, c);
|
||||
if (FONT_OBJECT_P (font_object))
|
||||
{
|
||||
font_fill_lglyph_metrics (g, font_object);
|
||||
}
|
||||
|
||||
if (font != NULL)
|
||||
code = font->driver->encode_char (font, LGLYPH_CHAR (g));
|
||||
else
|
||||
code = FONT_INVALID_CODE;
|
||||
if (code != FONT_INVALID_CODE)
|
||||
{
|
||||
font_fill_lglyph_metrics (g, font, code);
|
||||
}
|
||||
else
|
||||
{
|
||||
int width = XFIXNAT (CHAR_TABLE_REF (Vchar_width_table, c));
|
||||
|
|
|
@ -4416,10 +4416,8 @@ DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
|
|||
|
||||
|
||||
void
|
||||
font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
|
||||
font_fill_lglyph_metrics (Lisp_Object glyph, struct font *font, unsigned int code)
|
||||
{
|
||||
struct font *font = XFONT_OBJECT (font_object);
|
||||
unsigned code = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
|
||||
struct font_metrics metrics;
|
||||
|
||||
LGLYPH_SET_CODE (glyph, code);
|
||||
|
|
|
@ -886,7 +886,7 @@ extern Lisp_Object font_update_drivers (struct frame *f, Lisp_Object list);
|
|||
extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *,
|
||||
struct window *, struct face *,
|
||||
Lisp_Object);
|
||||
extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object);
|
||||
extern void font_fill_lglyph_metrics (Lisp_Object, struct font *, unsigned int);
|
||||
|
||||
extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,
|
||||
Lisp_Object val);
|
||||
|
|
|
@ -1039,9 +1039,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
|
|||
}
|
||||
|
||||
/* Given Lisp operands A and B, add their values, and return the
|
||||
result as a Lisp timestamp that is in (TICKS . HZ) form if either A
|
||||
or B are in that form or are floats, (HI LO US PS) form otherwise.
|
||||
Subtract instead of adding if SUBTRACT. */
|
||||
result as a Lisp timestamp. Subtract instead of adding if SUBTRACT. */
|
||||
static Lisp_Object
|
||||
time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
|
||||
{
|
||||
|
|
|
@ -4701,6 +4701,10 @@ static short temp_buffer[100];
|
|||
/* Temporarily store lead byte of DBCS input sequences. */
|
||||
static char dbcs_lead = 0;
|
||||
|
||||
/* Temporarily store pending UTF-16 high surrogate unit and the modifiers. */
|
||||
static unsigned short utf16_high;
|
||||
static DWORD utf16_high_modifiers;
|
||||
|
||||
/**
|
||||
mouse_or_wdesc_frame: When not dropping and the mouse was grabbed
|
||||
for DPYINFO, return the frame where the mouse was seen last. If
|
||||
|
@ -4912,9 +4916,45 @@ w32_read_socket (struct terminal *terminal,
|
|||
XSETFRAME (inev.frame_or_window, f);
|
||||
inev.timestamp = msg.msg.time;
|
||||
|
||||
if (utf16_high
|
||||
&& (msg.msg.message != WM_UNICHAR
|
||||
|| UTF_16_HIGH_SURROGATE_P (msg.msg.wParam)))
|
||||
{
|
||||
/* Flush the pending high surrogate if the low one
|
||||
isn't coming. (This should never happen, but I
|
||||
have paranoia about this stuff.) */
|
||||
struct input_event inev1;
|
||||
inev1.modifiers = utf16_high_modifiers;
|
||||
inev1.code = utf16_high;
|
||||
inev1.timestamp = inev.timestamp;
|
||||
inev1.arg = Qnil;
|
||||
kbd_buffer_store_event_hold (&inev1, hold_quit);
|
||||
utf16_high = 0;
|
||||
utf16_high_modifiers = 0;
|
||||
}
|
||||
|
||||
if (msg.msg.message == WM_UNICHAR)
|
||||
{
|
||||
inev.code = msg.msg.wParam;
|
||||
/* Handle UTF-16 encoded codepoint above the BMP.
|
||||
This is needed to support Emoji input from input
|
||||
panel popped up by "Win+." shortcut. */
|
||||
if (UTF_16_HIGH_SURROGATE_P (msg.msg.wParam))
|
||||
{
|
||||
utf16_high = msg.msg.wParam;
|
||||
utf16_high_modifiers = inev.modifiers;
|
||||
inev.kind = NO_EVENT;
|
||||
break;
|
||||
}
|
||||
else if (UTF_16_LOW_SURROGATE_P (msg.msg.wParam)
|
||||
&& utf16_high)
|
||||
{
|
||||
inev.code = surrogates_to_codepoint (msg.msg.wParam,
|
||||
utf16_high);
|
||||
utf16_high = 0;
|
||||
utf16_high_modifiers = 0;
|
||||
}
|
||||
else
|
||||
inev.code = msg.msg.wParam;
|
||||
}
|
||||
else if (msg.msg.wParam < 256)
|
||||
{
|
||||
|
|
|
@ -42,13 +42,24 @@
|
|||
(ert-deftest rx-or ()
|
||||
(should (equal (rx (or "ab" (| "c" nonl) "de"))
|
||||
"ab\\|c\\|.\\|de"))
|
||||
(should (equal (rx (or "ab" "abc" "a"))
|
||||
(should (equal (rx (or "ab" "abc" ?a))
|
||||
"\\(?:a\\(?:bc?\\)?\\)"))
|
||||
(should (equal (rx (or "ab" (| (or "abcd" "abcde")) (or "a" "abc")))
|
||||
"\\(?:a\\(?:b\\(?:c\\(?:de?\\)?\\)?\\)?\\)"))
|
||||
(should (equal (rx (or "a" (eval (string ?a ?b))))
|
||||
"\\(?:ab?\\)"))
|
||||
(should (equal (rx (| nonl "a") (| "b" blank))
|
||||
"\\(?:.\\|a\\)\\(?:b\\|[[:blank:]]\\)"))
|
||||
(should (equal (rx (|))
|
||||
"\\`a\\`")))
|
||||
|
||||
(ert-deftest rx-def-in-or ()
|
||||
(rx-let ((a b)
|
||||
(b (or "abc" c))
|
||||
(c ?a))
|
||||
(should (equal (rx (or a (| "ab" "abcde") "abcd"))
|
||||
"\\(?:a\\(?:b\\(?:c\\(?:de?\\)?\\)?\\)?\\)"))))
|
||||
|
||||
(ert-deftest rx-char-any ()
|
||||
"Test character alternatives with `]' and `-' (Bug#25123)."
|
||||
(should (equal
|
||||
|
@ -130,7 +141,10 @@
|
|||
(should (equal (rx (any "") (not (any "")))
|
||||
"\\`a\\`[^z-a]"))
|
||||
(should (equal (rx (any space ?a digit space))
|
||||
"[a[:space:][:digit:]]")))
|
||||
"[a[:space:][:digit:]]"))
|
||||
(should (equal (rx (not "\n") (not ?\n) (not (any "\n")) (not-char ?\n)
|
||||
(| (not (in "a\n")) (not (char ?\n (?b . ?b)))))
|
||||
".....")))
|
||||
|
||||
(ert-deftest rx-pcase ()
|
||||
(should (equal (pcase "a 1 2 3 1 1 b"
|
||||
|
@ -298,7 +312,11 @@
|
|||
(not (any "a-k"))))
|
||||
"[^abh-k]"))
|
||||
(should (equal (rx (or ?f (any "b-e") "a") (not (or ?x "y" (any "s-w"))))
|
||||
"[a-f][^s-y]")))
|
||||
"[a-f][^s-y]"))
|
||||
(should (equal (rx (not (or (in "abc") (char "bcd"))))
|
||||
"[^a-d]"))
|
||||
(should (equal (rx (or (not (in "abc")) (not (char "bcd"))))
|
||||
"[^bc]")))
|
||||
|
||||
(ert-deftest rx-def-in-charset-or ()
|
||||
(rx-let ((a (any "badc"))
|
||||
|
|
Loading…
Add table
Reference in a new issue