mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-23 14:32:12 -07:00
Merge commit '9cbdf20316' into native-comp
This commit is contained in:
commit
43b0df62cd
227 changed files with 37660 additions and 40546 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -254,6 +254,8 @@ doc/*/*/*.ps
|
|||
doc/emacs/emacsver.texi
|
||||
doc/man/emacs.1
|
||||
doc/misc/cc-mode.ss
|
||||
doc/misc/modus-themes.texi
|
||||
doc/misc/org.texi
|
||||
etc/DOC
|
||||
etc/refcards/emacsver.tex
|
||||
gnustmp*
|
||||
|
|
|
|||
48
Makefile.in
48
Makefile.in
|
|
@ -168,9 +168,6 @@ infodir=@infodir@
|
|||
# Info files not in the doc/misc directory (we get those via make echo-info).
|
||||
INFO_NONMISC=emacs.info eintr.info elisp.info
|
||||
|
||||
# If no makeinfo was found and configured --without-makeinfo, "no"; else "yes".
|
||||
HAVE_MAKEINFO=@HAVE_MAKEINFO@
|
||||
|
||||
# Directory for local state files for all programs.
|
||||
localstatedir=@localstatedir@
|
||||
|
||||
|
|
@ -661,9 +658,6 @@ install-etcdoc: src install-arch-indep
|
|||
## If info/dir is missing, but we have install-info, we should let
|
||||
## that handle it. If info/dir is present and we do not have install-info,
|
||||
## we should check for missing entries and add them by hand.
|
||||
##
|
||||
## FIXME:
|
||||
## If HAVE_MAKEINFO = no and there are no info files, do not install info/dir.
|
||||
install-info: info
|
||||
umask 022; ${MKDIR_P} "$(DESTDIR)${infodir}"
|
||||
-unset CDPATH; \
|
||||
|
|
@ -675,10 +669,9 @@ install-info: info
|
|||
[ -f "$(DESTDIR)${infodir}/dir" ] || \
|
||||
[ ! -f ${srcdir}/info/dir ] || \
|
||||
${INSTALL_DATA} ${srcdir}/info/dir "$(DESTDIR)${infodir}/dir"; \
|
||||
info_misc=`$(MAKE) --no-print-directory -s -C doc/misc echo-info`; \
|
||||
info_misc=`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc echo-info`; \
|
||||
cd ${srcdir}/info ; \
|
||||
for elt in ${INFO_NONMISC} $${info_misc}; do \
|
||||
test "$(HAVE_MAKEINFO)" = "no" && test ! -f $$elt && continue; \
|
||||
for f in `ls $$elt $$elt-[1-9] $$elt-[1-9][0-9] 2>/dev/null`; do \
|
||||
(cd "$${thisdir}"; \
|
||||
${INSTALL_DATA} ${srcdir}/info/$$f "$(DESTDIR)${infodir}/$$f"); \
|
||||
|
|
@ -796,7 +789,7 @@ uninstall: uninstall-$(NTDIR) uninstall-doc
|
|||
done
|
||||
-rm -rf "$(DESTDIR)${libexecdir}/emacs/${version}"
|
||||
thisdir=`/bin/pwd`; \
|
||||
(info_misc=`$(MAKE) --no-print-directory -s -C doc/misc echo-info`; \
|
||||
(info_misc=`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc echo-info`; \
|
||||
if cd "$(DESTDIR)${infodir}"; then \
|
||||
for elt in ${INFO_NONMISC} $${info_misc}; do \
|
||||
(cd "$${thisdir}"; \
|
||||
|
|
@ -1005,24 +998,34 @@ $(DOCS):
|
|||
$(MAKE) -C doc/$(subst -, ,$@)
|
||||
|
||||
.PHONY: $(DOCS) docs pdf ps
|
||||
.PHONY: info dvi dist html info-real info-dir check-info
|
||||
.PHONY: info dvi dist html info-dir check-info
|
||||
|
||||
## TODO add etc/refcards.
|
||||
docs: $(DOCS)
|
||||
dvi: $(DVIS)
|
||||
html: $(HTMLS)
|
||||
info-real: $(INFOS)
|
||||
info: $(INFOS) info-dir
|
||||
pdf: $(PDFS)
|
||||
ps: $(PSS)
|
||||
|
||||
# This dependency is due to those doc/misc/ manuals that use .org sources.
|
||||
# Depending on src is sufficient, but ends up being slow, since the
|
||||
# uncompiled lisp/org/*.el files are used to build the .texi files
|
||||
# (which can be slow even with the elc files).
|
||||
misc-info: lisp
|
||||
# Using src rather than lisp because one is less likely to get unnecessary
|
||||
# rebuilds of stuff that is not strictly necessary for generating manuals.
|
||||
misc-dvi misc-html misc-pdf misc-ps: src
|
||||
|
||||
info-dir: ${srcdir}/info/dir
|
||||
|
||||
## Hopefully doc/misc/*.texi is not too long for some systems?
|
||||
texi_misc = $(shell MAKEFLAGS= ${MAKE} --no-print-directory -s -C doc/misc echo-sources)
|
||||
|
||||
srcdir_doc_info_dir_inputs = \
|
||||
${srcdir}/doc/emacs/emacs.texi \
|
||||
${srcdir}/doc/lispintro/emacs-lisp-intro.texi \
|
||||
${srcdir}/doc/lispref/elisp.texi \
|
||||
$(sort $(wildcard ${srcdir}/doc/misc/*.texi))
|
||||
$(addprefix ${srcdir}/doc/misc/,${texi_misc})
|
||||
info_dir_inputs = \
|
||||
../build-aux/dir_top \
|
||||
$(subst ${srcdir}/doc/,,${srcdir_doc_info_dir_inputs})
|
||||
|
|
@ -1035,7 +1038,7 @@ info_dir_deps = \
|
|||
## installation location by the install-info rule, but we also
|
||||
## need one in the source directory for people running uninstalled.
|
||||
## FIXME it would be faster to use the install-info program if we have it,
|
||||
## but then we would need to depend on info-real, which would
|
||||
## but then we would need to depend on ${INFOS}, which would
|
||||
## slow down parallelization.
|
||||
${srcdir}/info/dir: ${info_dir_deps}
|
||||
$(AM_V_at)${MKDIR_P} ${srcdir}/info
|
||||
|
|
@ -1090,23 +1093,6 @@ uninstall-html: $(UNINSTALL_HTML)
|
|||
uninstall-pdf: $(UNINSTALL_PDF)
|
||||
uninstall-ps: $(UNINSTALL_PS)
|
||||
|
||||
|
||||
# Note that man/Makefile knows how to put the info files in $(srcdir),
|
||||
# so we can do ok running make in the build dir.
|
||||
# This used to have a clause that exited with an error if MAKEINFO = no.
|
||||
# But it is inappropriate to do so without checking if makeinfo is
|
||||
# actually needed - it is not if the info files are up-to-date. (Bug#3982)
|
||||
# Only the doc/*/Makefiles can decide that, so we let those rules run
|
||||
# and give a standard error if makeinfo is needed but missing.
|
||||
# While it would be nice to give a more detailed error message, that
|
||||
# would require changing every rule in doc/ that builds an info file,
|
||||
# and it's not worth it. This case is only relevant if you download a
|
||||
# release, then change the .texi files.
|
||||
info:
|
||||
ifneq ($(HAVE_MAKEINFO),no)
|
||||
$(MAKE) info-real info-dir
|
||||
endif
|
||||
|
||||
## build-aux/make-info-dir expects only certain dircategories.
|
||||
check-info: info
|
||||
cd info ; \
|
||||
|
|
|
|||
|
|
@ -665,6 +665,8 @@ style=\"text-align:left\">")
|
|||
|
||||
(defconst make-manuals-dist-output-variables
|
||||
'(("@\\(top_\\)?srcdir@" . ".") ; top_srcdir is wrong, but not used
|
||||
("@abs_top_builddir@" . ".") ; wrong but unused
|
||||
("^\\(EMACS *=\\).*" . "\\1 emacs")
|
||||
("^\\(\\(?:texinfo\\|buildinfo\\|emacs\\)dir *=\\).*" . "\\1 .")
|
||||
("^\\(clean:.*\\)" . "\\1 infoclean")
|
||||
("@MAKEINFO@" . "makeinfo")
|
||||
|
|
@ -714,7 +716,8 @@ style=\"text-align:left\">")
|
|||
(string-match-p "\\.\\(eps\\|pdf\\)\\'" file)))
|
||||
(copy-file file stem)))
|
||||
(with-temp-buffer
|
||||
(let ((outvars make-manuals-dist-output-variables))
|
||||
(let ((outvars make-manuals-dist-output-variables)
|
||||
(case-fold-search nil))
|
||||
(push `("@version@" . ,version) outvars)
|
||||
(insert-file-contents (format "../doc/%s/Makefile.in" type))
|
||||
(dolist (cons outvars)
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ typesimple
|
|||
: struct-or-class opt-class opt-name opt-template-specifier
|
||||
opt-class-parents semantic-list
|
||||
(TYPE-TAG (car $3) (car $1)
|
||||
(let ((semantic-c-classname (cons (car ,$3) (car ,$1))))
|
||||
(dlet ((semantic-c-classname (cons (car ,$3) (car ,$1))))
|
||||
(EXPANDFULL $6 classsubparts))
|
||||
$5
|
||||
:template-specifier $4
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
|
||||
%package wisent-python-wy
|
||||
%provide semantic/wisent/python-wy
|
||||
%expectedconflicts 4
|
||||
%expectedconflicts 5
|
||||
|
||||
%{
|
||||
(declare-function wisent-python-reconstitute-function-tag
|
||||
|
|
@ -184,6 +184,7 @@
|
|||
%token <punctuation> ASSIGN "="
|
||||
%token <punctuation> BACKQUOTE "`"
|
||||
%token <punctuation> AT "@"
|
||||
%token <punctuation> FOLLOWS "->"
|
||||
|
||||
|
||||
;; -----------------
|
||||
|
|
@ -808,12 +809,17 @@ decorators
|
|||
|
||||
;; funcdef: [decorators] 'def' NAME parameters ':' suite
|
||||
funcdef
|
||||
: DEF NAME function_parameter_list COLON suite
|
||||
: DEF NAME function_parameter_list return_type_hint COLON suite
|
||||
(wisent-python-reconstitute-function-tag
|
||||
(FUNCTION-TAG $2 nil $3) $5)
|
||||
| decorators DEF NAME function_parameter_list COLON suite
|
||||
(FUNCTION-TAG $2 nil $3) $6)
|
||||
| decorators DEF NAME function_parameter_list return_type_hint COLON suite
|
||||
(wisent-python-reconstitute-function-tag
|
||||
(FUNCTION-TAG $3 nil $4 :decorators $1) $6)
|
||||
(FUNCTION-TAG $3 nil $4 :decorators $1) $7)
|
||||
;
|
||||
|
||||
return_type_hint
|
||||
: ;;EMPTY
|
||||
| FOLLOWS type
|
||||
;
|
||||
|
||||
function_parameter_list
|
||||
|
|
@ -887,7 +893,7 @@ paren_classes
|
|||
;; parser can parse general expressions, I don't see much benefit in
|
||||
;; generating a string of expression as base class "name".
|
||||
paren_class
|
||||
: dotted_name
|
||||
: type
|
||||
;
|
||||
|
||||
;;;****************************************************************************
|
||||
|
|
@ -1140,7 +1146,7 @@ fpdef_opt_test
|
|||
|
||||
;; fpdef: NAME | '(' fplist ')'
|
||||
fpdef
|
||||
: NAME
|
||||
: NAME type_hint
|
||||
(VARIABLE-TAG $1 nil nil)
|
||||
;; Below breaks the parser. Don't know why, but my guess is that
|
||||
;; LPAREN/RPAREN clashes with the ones in function_parameters.
|
||||
|
|
@ -1160,6 +1166,15 @@ fpdef
|
|||
;; | fpdef_list COMMA fpdef
|
||||
;; ;
|
||||
|
||||
type_hint
|
||||
: ;;EMPTY
|
||||
| COLON type
|
||||
;
|
||||
|
||||
type
|
||||
: test
|
||||
;
|
||||
|
||||
;; ['=' test]
|
||||
eq_test_opt
|
||||
: ;;EMPTY
|
||||
|
|
|
|||
|
|
@ -52,8 +52,11 @@ exec "${AWK-awk}" '
|
|||
topic[ntopics++] = "Emacs misc features"
|
||||
topic[ntopics++] = "Emacs lisp libraries"
|
||||
topic[ntopics] = "Unknown category"
|
||||
texinfo = 0
|
||||
}
|
||||
|
||||
/^@dircategory / {
|
||||
texinfo = 1
|
||||
sub(/^@dircategory /, "")
|
||||
detexinfo()
|
||||
for (dircat = 0; dircat < ntopics && topic[dircat] != $0; dircat++)
|
||||
|
|
@ -66,6 +69,33 @@ exec "${AWK-awk}" '
|
|||
data[dircat] = data[dircat] $0 "\n"
|
||||
}
|
||||
}
|
||||
|
||||
## Org stuff. TODO we assume the order of the texinfo items.
|
||||
{
|
||||
## TODO Check FILENAME suffix instead?
|
||||
## TODO Is this portable awk?
|
||||
if (FNR == 1) texinfo = 0
|
||||
|
||||
## If applied to the generated org.texi file, this picks up the examples.
|
||||
## Thanks for making life more difficult...
|
||||
if (texinfo) next
|
||||
|
||||
if (tolower($0) ~ /^#\+texinfo_dir_category/) {
|
||||
sub(/^#[^:]*: /, "")
|
||||
for (dircat = 0; dircat < ntopics && topic[dircat] != $0; dircat++)
|
||||
continue;
|
||||
}
|
||||
if (tolower($0) ~ /^#\+texinfo_dir_title/) {
|
||||
sub(/^#[^:]*: /, "")
|
||||
## Note this does not fill any long descriptions.
|
||||
data[dircat] = data[dircat] sprintf("* %-30s", ($0 ". "))
|
||||
}
|
||||
if (tolower($0) ~ /^#\+texinfo_dir_desc/) {
|
||||
sub(/^#[^:]*: /, "")
|
||||
data[dircat] = data[dircat] $0 ".\n"
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
for (dircat = 0; dircat <= ntopics; dircat++)
|
||||
if (data[dircat])
|
||||
|
|
|
|||
34
configure.ac
34
configure.ac
|
|
@ -508,11 +508,6 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' that is usable.])
|
|||
OPTION_DEFAULT_OFF([xwidgets],
|
||||
[enable use of xwidgets in Emacs buffers (requires gtk3 or macOS Cocoa)])
|
||||
|
||||
## For the times when you want to build Emacs but don't have
|
||||
## a suitable makeinfo, and can live without the manuals.
|
||||
dnl https://lists.gnu.org/r/emacs-devel/2008-04/msg01844.html
|
||||
OPTION_DEFAULT_ON([makeinfo],[don't require makeinfo for building manuals])
|
||||
|
||||
## Makefile.in needs the cache file name.
|
||||
AC_SUBST(cache_file)
|
||||
|
||||
|
|
@ -1346,14 +1341,13 @@ if test -n "$BREW"; then
|
|||
fi
|
||||
|
||||
## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals.
|
||||
if test "${MAKEINFO:=makeinfo}" != "no"; then
|
||||
case `($MAKEINFO --version) 2>/dev/null` in
|
||||
*' (GNU texinfo) '4.1[[3-9]]* | \
|
||||
*' (GNU texinfo) '[[5-9]]* | \
|
||||
*' (GNU texinfo) '[[1-9][0-9]]* ) ;;
|
||||
*) MAKEINFO=no;;
|
||||
esac
|
||||
fi
|
||||
: ${MAKEINFO:=makeinfo}
|
||||
case `($MAKEINFO --version) 2>/dev/null` in
|
||||
*' (GNU texinfo) '4.1[[3-9]]* | \
|
||||
*' (GNU texinfo) '[[5-9]]* | \
|
||||
*' (GNU texinfo) '[[1-9][0-9]]* ) ;;
|
||||
*) MAKEINFO=no;;
|
||||
esac
|
||||
|
||||
## Makeinfo is unusual. For a released Emacs, the manuals are
|
||||
## pre-built, and not deleted by the normal clean rules. makeinfo is
|
||||
|
|
@ -1364,21 +1358,19 @@ fi
|
|||
## should test for it as it does for any other build requirement.
|
||||
## We use the presence of $srcdir/info/emacs to distinguish a release,
|
||||
## with pre-built manuals, from a repository checkout.
|
||||
HAVE_MAKEINFO=yes
|
||||
|
||||
if test "$MAKEINFO" = "no"; then
|
||||
MAKEINFO=makeinfo
|
||||
if test "x${with_makeinfo}" = "xno"; then
|
||||
HAVE_MAKEINFO=no
|
||||
elif test ! -e "$srcdir/info/emacs" && test ! -e "$srcdir/info/emacs.info"; then
|
||||
if test ! -e "$srcdir/info/emacs" && test ! -e "$srcdir/info/emacs.info"; then
|
||||
AC_MSG_ERROR( [You do not seem to have makeinfo >= 4.13, and your
|
||||
source tree does not seem to have pre-built manuals in the 'info' directory.
|
||||
Either install a suitable version of makeinfo, or re-run configure
|
||||
with the '--without-makeinfo' option to build without the manuals.] )
|
||||
Please install a suitable version of makeinfo.] )
|
||||
else
|
||||
AC_MSG_WARN( [You do not seem to have makeinfo >= 4.13.
|
||||
You will not be able to rebuild the manuals if you delete them or change
|
||||
their sources.] )
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([MAKEINFO])
|
||||
AC_SUBST(HAVE_MAKEINFO)
|
||||
|
||||
if test $opsys = mingw32; then
|
||||
DOCMISC_W32=efaq-w32
|
||||
|
|
|
|||
|
|
@ -126,6 +126,13 @@ line; typing @kbd{x} (see below) will delete the package.
|
|||
@xref{Package Files}, for information about what package deletion
|
||||
entails.
|
||||
|
||||
@item w
|
||||
@kindex w @r{(Package Menu)}
|
||||
@findex package-browse-url
|
||||
Open the home page of the package on the current line in a browser
|
||||
(@code{package-browse-url}). @code{browse-url} is used to open the
|
||||
browser.
|
||||
|
||||
@item ~
|
||||
@kindex ~ @r{(Package Menu)}
|
||||
@findex package-menu-mark-obsolete-for-deletion
|
||||
|
|
|
|||
|
|
@ -617,17 +617,13 @@ match, @code{and} matches.
|
|||
@item (or @var{pattern1} @var{pattern2}@dots{})
|
||||
Attempts to match @var{pattern1}, @var{pattern2}, @dots{}, in order,
|
||||
until one of them succeeds. In that case, @code{or} likewise matches,
|
||||
and the rest of the sub-patterns are not tested. (Note that there
|
||||
must be at least two sub-patterns.
|
||||
Simply @w{@code{(or @var{pattern1})}} signals error.)
|
||||
@c Issue: Is this correct and intended?
|
||||
@c Are there exceptions, qualifications?
|
||||
@c (Btw, ``Please avoid it'' is a poor error message.)
|
||||
and the rest of the sub-patterns are not tested.
|
||||
|
||||
To present a consistent environment (@pxref{Intro Eval})
|
||||
to @var{body-forms} (thus avoiding an evaluation error on match),
|
||||
if any of the sub-patterns let-binds a set of symbols,
|
||||
they @emph{must} all bind the same set of symbols.
|
||||
the set of variables bound by the pattern is the union of the
|
||||
variables bound by each sub-pattern. If a variable is not bound by
|
||||
the sub-pattern that matched, then it is bound to @code{nil}.
|
||||
|
||||
@ifnottex
|
||||
@anchor{rx in pcase}
|
||||
|
|
|
|||
|
|
@ -1474,7 +1474,7 @@ To protect against loading themes containing malicious code, Emacs
|
|||
displays the source file and asks for confirmation from the user
|
||||
before loading any non-built-in theme for the first time. As
|
||||
such, themes are not ordinarily byte-compiled, and source files
|
||||
always take precedence when Emacs is looking for a theme to load.
|
||||
usually take precedence when Emacs is looking for a theme to load.
|
||||
|
||||
The following functions are useful for programmatically enabling and
|
||||
disabling themes:
|
||||
|
|
@ -1508,6 +1508,30 @@ confirmation before loading the theme, unless the optional argument
|
|||
@var{no-confirm} is non-@code{nil}.
|
||||
@end deffn
|
||||
|
||||
@defun require-theme feature &optional noerror
|
||||
This function searches @code{custom-theme-load-path} for a file that
|
||||
provides @var{feature} and then loads it. This is like the function
|
||||
@code{require} (@pxref{Named Features}), except it searches
|
||||
@code{custom-theme-load-path} instead of @code{load-path}
|
||||
(@pxref{Library Search}). This can be useful in Custom themes that
|
||||
need to load supporting Lisp files when @code{require} is unsuitable
|
||||
for that.
|
||||
|
||||
If @var{feature}, which should be a symbol, is not already present in
|
||||
the current Emacs session according to @code{featurep}, then
|
||||
@code{require-theme} searches for a file named @var{feature} with an
|
||||
added @samp{.elc} or @samp{.el} suffix, in that order, in the
|
||||
directories specified by @code{custom-theme-load-path}.
|
||||
|
||||
If a file providing @var{feature} is successfully found and loaded,
|
||||
then @code{require-theme} returns @var{feature}. The optional
|
||||
argument @var{noerror} determines what happens if the search or
|
||||
loading fails. If it is @code{nil}, the function signals an error;
|
||||
otherwise, it returns @code{nil}. If the file loads successfully but
|
||||
does not provide @var{feature}, then @code{require-theme} signals an
|
||||
error; this cannot be suppressed.
|
||||
@end defun
|
||||
|
||||
@deffn Command enable-theme theme
|
||||
This function enables the Custom theme named @var{theme}. It signals
|
||||
an error if no such theme has been loaded.
|
||||
|
|
|
|||
|
|
@ -1408,8 +1408,9 @@ Low-Level Network Access
|
|||
|
||||
Packing and Unpacking Byte Arrays
|
||||
|
||||
* Bindat Spec:: Describing data layout.
|
||||
* Bindat Types:: Describing data layout.
|
||||
* Bindat Functions:: Doing the unpacking and packing.
|
||||
* Bindat Computed Types:: Advanced data layout specifications.
|
||||
|
||||
Emacs Display
|
||||
|
||||
|
|
|
|||
|
|
@ -1181,7 +1181,7 @@ This form defines a method like @code{cl-defmethod} does.
|
|||
@end table
|
||||
@end defmac
|
||||
|
||||
@defmac cl-defmethod name [qualifier] arguments [&context (expr spec)@dots{}] &rest [docstring] body
|
||||
@defmac cl-defmethod name [extra] [qualifier] arguments [&context (expr spec)@dots{}] &rest [docstring] body
|
||||
This macro defines a particular implementation for the generic
|
||||
function called @var{name}. The implementation code is given by
|
||||
@var{body}. If present, @var{docstring} is the documentation string
|
||||
|
|
@ -1267,6 +1267,10 @@ Parent type: @code{array}.
|
|||
@item font-object
|
||||
@end table
|
||||
|
||||
The optional @var{extra} element, expressed as @samp{:extra
|
||||
@var{string}}, allows you to add more methods, distinguished by
|
||||
@var{string}, for the same specializers and qualifiers.
|
||||
|
||||
The optional @var{qualifier} allows combining several applicable
|
||||
methods. If it is not present, the defined method is a @dfn{primary}
|
||||
method, responsible for providing the primary implementation of the
|
||||
|
|
@ -1288,9 +1292,6 @@ This auxiliary method will run @emph{instead} of the primary method.
|
|||
The most specific of such methods will be run before any other method.
|
||||
Such methods normally use @code{cl-call-next-method}, described below,
|
||||
to invoke the other auxiliary or primary methods.
|
||||
@item :extra @var{string}
|
||||
This allows you to add more methods, distinguished by @var{string},
|
||||
for the same specializers and qualifiers.
|
||||
@end table
|
||||
|
||||
Functions defined using @code{cl-defmethod} cannot be made
|
||||
|
|
|
|||
|
|
@ -701,8 +701,9 @@ A history list for numbers read by @code{read-number}.
|
|||
@end defvar
|
||||
|
||||
@defvar goto-line-history
|
||||
A history list for arguments to @code{goto-line}. This variable is
|
||||
buffer local.
|
||||
A history list for arguments to @code{goto-line}. This variable can
|
||||
be made local in every buffer by customizing the user option
|
||||
@code{goto-line-history-local}.
|
||||
@end defvar
|
||||
|
||||
@c Less common: coding-system-history, input-method-history,
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ other strings to choose various seed values.
|
|||
This function returns a pseudo-random integer. Repeated calls return a
|
||||
series of pseudo-random integers.
|
||||
|
||||
If @var{limit} is a positive fixnum, the value is chosen to be
|
||||
If @var{limit} is a positive integer, the value is chosen to be
|
||||
nonnegative and less than @var{limit}. Otherwise, the value might be
|
||||
any fixnum, i.e., any integer from @code{most-negative-fixnum} through
|
||||
@code{most-positive-fixnum} (@pxref{Integer Basics}).
|
||||
|
|
|
|||
|
|
@ -3354,29 +3354,37 @@ To use the functions referred to in this section, load the
|
|||
direction is also known as @dfn{serializing} or @dfn{packing}.
|
||||
|
||||
@menu
|
||||
* Bindat Spec:: Describing data layout.
|
||||
* Bindat Functions:: Doing the unpacking and packing.
|
||||
* Bindat Types:: Describing data layout.
|
||||
* Bindat Functions:: Doing the unpacking and packing.
|
||||
* Bindat Computed Types:: Advanced data layout specifications.
|
||||
@end menu
|
||||
|
||||
@node Bindat Spec
|
||||
@node Bindat Types
|
||||
@subsection Describing Data Layout
|
||||
@cindex bindat types
|
||||
|
||||
@cindex data layout specification
|
||||
@cindex bindat type expression
|
||||
@cindex base type, in bindat specification
|
||||
@cindex composite type, in bindat specification
|
||||
To control unpacking and packing, you write a @dfn{data layout
|
||||
specification}, a special nested list describing named and typed
|
||||
@dfn{fields}. This specification controls the length of each field to be
|
||||
processed, and how to pack or unpack it. We normally keep bindat specs
|
||||
in variables whose names end in @samp{-bindat-spec}; that kind of name
|
||||
is automatically recognized as risky.
|
||||
specification}, also called a @dfn{Bindat type expression}. This can
|
||||
be a @dfn{base type} or a @dfn{composite type} made of several fields,
|
||||
where the specification controls the length of each field to be
|
||||
processed, and how to pack or unpack it. We normally keep bindat type
|
||||
values in variables whose names end in @code{-bindat-spec}; that kind
|
||||
of name is automatically recognized as risky (@pxref{File Local
|
||||
Variables}).
|
||||
|
||||
@defmac bindat-spec &rest specs
|
||||
Creates a Bindat spec object according to the data layout
|
||||
specification @var{specs}.
|
||||
@defmac bindat-type &rest type
|
||||
Creates a Bindat type @emph{value} object according to the Bindat type
|
||||
@emph{expression} @var{type}.
|
||||
@end defmac
|
||||
|
||||
@cindex endianness
|
||||
@cindex big endian
|
||||
@cindex little endian
|
||||
@cindex network byte ordering
|
||||
@cindex endianness, in bindat specification
|
||||
@cindex big endian, in bindat specification
|
||||
@cindex little endian, in bindat specification
|
||||
@cindex network byte ordering, in Bindat specification
|
||||
A field's @dfn{type} describes the size (in bytes) of the object
|
||||
that the field represents and, in the case of multibyte fields, how
|
||||
the bytes are ordered within the field. The two possible orderings
|
||||
|
|
@ -3391,167 +3399,90 @@ type values:
|
|||
@itemx byte
|
||||
Unsigned byte, with length 1.
|
||||
|
||||
@item u16
|
||||
@itemx word
|
||||
@itemx short
|
||||
Unsigned integer in network byte order, with length 2.
|
||||
@item uint @var{bitlen}
|
||||
Unsigned integer in network byte order, with @var{bitlen} bits.
|
||||
@var{bitlen} has to be a multiple of 8.
|
||||
|
||||
@item u24
|
||||
Unsigned integer in network byte order, with length 3.
|
||||
|
||||
@item u32
|
||||
@itemx dword
|
||||
@itemx long
|
||||
Unsigned integer in network byte order, with length 4.
|
||||
|
||||
@item u64
|
||||
Unsigned integer in network byte order, with length 8.
|
||||
|
||||
@item u16r
|
||||
@itemx u24r
|
||||
@itemx u32r
|
||||
@itemx u64r
|
||||
Unsigned integer in little endian order, with length 2, 3, 4, and
|
||||
8, respectively.
|
||||
@item uintr @var{bitlen}
|
||||
Unsigned integer in little endian order, with @var{bitlen} bits.
|
||||
@var{bitlen} has to be a multiple of 8.
|
||||
|
||||
@item str @var{len}
|
||||
String of length @var{len}.
|
||||
String of bytes of length @var{len}.
|
||||
|
||||
@item strz @var{len}
|
||||
Zero-terminated string, in a fixed-size field with length @var{len}.
|
||||
Zero-terminated string of bytes, in a fixed-size field with length @var{len}.
|
||||
|
||||
@item vec @var{len} [@var{type}]
|
||||
Vector of @var{len} elements of type @var{type}, defaulting to bytes.
|
||||
The @var{type} is any of the simple types above, or another vector
|
||||
specified as a list of the form @code{(vec @var{len} [@var{type}])}.
|
||||
Vector of @var{len} elements. The type of the elements is given by
|
||||
@var{type}, defaulting to bytes. The @var{type} can be any Bindat
|
||||
type expression.
|
||||
|
||||
@item ip
|
||||
@c FIXME? IPv6?
|
||||
Four-byte vector representing an Internet address. For example:
|
||||
@code{[127 0 0 1]} for localhost.
|
||||
@item repeat @var{len} [@var{type}]
|
||||
Like @code{vec}, but it unpacks to and packs from lists, whereas
|
||||
@code{vec} unpacks to vectors.
|
||||
|
||||
@item bits @var{len}
|
||||
List of set bits in @var{len} bytes. The bytes are taken in big
|
||||
endian order and the bits are numbered starting with @code{8 *
|
||||
@var{len} @minus{} 1} and ending with zero. For example: @code{bits
|
||||
2} unpacks @code{#x28} @code{#x1c} to @code{(2 3 4 11 13)} and
|
||||
@code{#x1c} @code{#x28} to @code{(3 5 10 11 12)}.
|
||||
|
||||
@item (eval @var{form})
|
||||
@var{form} is a Lisp expression evaluated at the moment the field is
|
||||
unpacked or packed. The result of the evaluation should be one of the
|
||||
above-listed type specifications.
|
||||
@end table
|
||||
|
||||
For a fixed-size field, the length @var{len} is given as an integer
|
||||
specifying the number of bytes in the field.
|
||||
|
||||
When the length of a field is not fixed, it typically depends on the
|
||||
value of a preceding field. In this case, the length @var{len} can be
|
||||
given either as a list @code{(@var{name} ...)} identifying a
|
||||
@dfn{field name} in the format specified for @code{bindat-get-field}
|
||||
below, or by an expression @code{(eval @var{form})} where @var{form}
|
||||
should evaluate to an integer, specifying the field length.
|
||||
|
||||
A field specification generally has the form @code{([@var{name}]
|
||||
@var{handler})}, where @var{name} is optional. Don't use names that
|
||||
are symbols meaningful as type specifications (above) or handler
|
||||
specifications (below), since that would be ambiguous. @var{name} can
|
||||
be a symbol or an expression @code{(eval @var{form})}, in which case
|
||||
@var{form} should evaluate to a symbol.
|
||||
|
||||
@var{handler} describes how to unpack or pack the field and can be one
|
||||
of the following:
|
||||
|
||||
@table @code
|
||||
@item @var{type}
|
||||
Unpack/pack this field according to the type specification @var{type}.
|
||||
|
||||
@item eval @var{form}
|
||||
Evaluate @var{form}, a Lisp expression, for side-effect only. If the
|
||||
field name is specified, the value is bound to that field name.
|
||||
List of bits that are set to 1 in @var{len} bytes. The bytes are
|
||||
taken in big-endian order, and the bits are numbered starting with
|
||||
@code{8 * @var{len} @minus{} 1} and ending with zero. For example:
|
||||
@code{bits 2} unpacks @code{#x28} @code{#x1c} to @w{@code{(2 3 4 11 13)}}
|
||||
and @code{#x1c} @code{#x28} to @w{@code{(3 5 10 11 12)}}.
|
||||
|
||||
@item fill @var{len}
|
||||
Skip @var{len} bytes. In packing, this leaves them unchanged,
|
||||
which normally means they remain zero. In unpacking, this means
|
||||
they are ignored.
|
||||
@var{len} bytes used as a mere filler. In packing, these bytes are
|
||||
are left unchanged, which normally means they remain zero.
|
||||
When unpacking, this just returns nil.
|
||||
|
||||
@item align @var{len}
|
||||
Skip to the next multiple of @var{len} bytes.
|
||||
Same as @code{fill} except the number of bytes is that needed to skip
|
||||
to the next multiple of @var{len} bytes.
|
||||
|
||||
@item struct @var{spec-name}
|
||||
Process @var{spec-name} as a sub-specification. This describes a
|
||||
structure nested within another structure.
|
||||
@item type @var{exp}
|
||||
This lets you refer to a type indirectly: @var{exp} is a Lisp
|
||||
expression which should return a Bindat type @emph{value}.
|
||||
|
||||
@item union @var{form} (@var{tag} @var{spec})@dots{}
|
||||
@c ??? I don't see how one would actually use this.
|
||||
@c ??? what kind of expression would be useful for @var{form}?
|
||||
Evaluate @var{form}, a Lisp expression, find the first @var{tag}
|
||||
that matches it, and process its associated data layout specification
|
||||
@var{spec}. Matching can occur in one of three ways:
|
||||
@item unit @var{exp}
|
||||
This is a trivial type which uses up 0 bits of space. @var{exp}
|
||||
describes the value returned when we try to ``unpack'' such a field.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
If a @var{tag} has the form @code{(eval @var{expr})}, evaluate
|
||||
@var{expr} with the variable @code{tag} dynamically bound to the value
|
||||
of @var{form}. A non-@code{nil} result indicates a match.
|
||||
|
||||
@item
|
||||
@var{tag} matches if it is @code{equal} to the value of @var{form}.
|
||||
|
||||
@item
|
||||
@var{tag} matches unconditionally if it is @code{t}.
|
||||
@end itemize
|
||||
|
||||
@item repeat @var{count} @var{field-specs}@dots{}
|
||||
Process the @var{field-specs} recursively, in order, then repeat
|
||||
starting from the first one, processing all the specifications @var{count}
|
||||
times overall. The @var{count} is given using the same formats as a
|
||||
field length---if an @code{eval} form is used, it is evaluated just once.
|
||||
For correct operation, each specification in @var{field-specs} must
|
||||
include a name.
|
||||
@item struct @var{fields}...
|
||||
Composite type made of several fields. Every field is of the form
|
||||
@code{(@var{name} @var{type})} where @var{type} can be any Bindat
|
||||
type expression. @var{name} can be @code{_} when the field's value
|
||||
does not deserve to be named, as is often the case for @code{align}
|
||||
and @code{fill} fields.
|
||||
When the context makes it clear that this is a Bindat type expression,
|
||||
the symbol @code{struct} can be omitted.
|
||||
@end table
|
||||
|
||||
For the @code{(eval @var{form})} forms used in a bindat specification,
|
||||
the @var{form} can access and update these dynamically bound variables
|
||||
during evaluation:
|
||||
In the types above, @var{len} and @var{bitlen} are given as an integer
|
||||
specifying the number of bytes (or bits) in the field. When the
|
||||
length of a field is not fixed, it typically depends on the value of
|
||||
preceding fields. For this reason, the length @var{len} does not have
|
||||
to be a constant but can be any Lisp expression and it can refer to
|
||||
the value of previous fields via their name.
|
||||
|
||||
@table @code
|
||||
@item last
|
||||
Value of the last field processed.
|
||||
|
||||
@item bindat-raw
|
||||
The data as a byte array.
|
||||
|
||||
@item bindat-idx
|
||||
Current index (within @code{bindat-raw}) for unpacking or packing.
|
||||
|
||||
@item struct
|
||||
The alist containing the structured data that have been unpacked so
|
||||
far, or the entire structure being packed. You can use
|
||||
@code{bindat-get-field} to access specific fields of this structure.
|
||||
|
||||
@item count
|
||||
@itemx index
|
||||
Inside a @code{repeat} block, these contain the maximum number of
|
||||
repetitions (as specified by the @var{count} parameter), and the
|
||||
current repetition number (counting from 0). Setting @code{count} to
|
||||
zero will terminate the inner-most repeat block after the current
|
||||
repetition has completed.
|
||||
@end table
|
||||
For example, the specification of a data layout where a leading byte gives
|
||||
the size of a subsequent vector of 16 bit integers could be:
|
||||
@example
|
||||
(bindat-type
|
||||
(len u8)
|
||||
(payload vec (1+ len) uint 16))
|
||||
@end example
|
||||
|
||||
@node Bindat Functions
|
||||
@subsection Functions to Unpack and Pack Bytes
|
||||
@cindex bindat functions
|
||||
|
||||
In the following documentation, @var{spec} refers to a Bindat spec
|
||||
object as returned from @code{bindat-spec}, @code{raw} to a byte
|
||||
In the following documentation, @var{type} refers to a Bindat type
|
||||
value as returned from @code{bindat-type}, @var{raw} to a byte
|
||||
array, and @var{struct} to an alist representing unpacked field data.
|
||||
|
||||
@defun bindat-unpack spec raw &optional idx
|
||||
@c FIXME? Again, no multibyte?
|
||||
@defun bindat-unpack type raw &optional idx
|
||||
This function unpacks data from the unibyte string or byte
|
||||
array @var{raw}
|
||||
according to @var{spec}. Normally, this starts unpacking at the
|
||||
according to @var{type}. Normally, this starts unpacking at the
|
||||
beginning of the byte array, but if @var{idx} is non-@code{nil}, it
|
||||
specifies a zero-based starting position to use instead.
|
||||
|
||||
|
|
@ -3564,12 +3495,13 @@ This function selects a field's data from the nested alist
|
|||
@var{struct}. Usually @var{struct} was returned by
|
||||
@code{bindat-unpack}. If @var{name} corresponds to just one argument,
|
||||
that means to extract a top-level field value. Multiple @var{name}
|
||||
arguments specify repeated lookup of sub-structures. An integer name
|
||||
acts as an array index.
|
||||
arguments specify repeated lookup of sub-structures. An integer
|
||||
@var{name} acts as an array index.
|
||||
|
||||
For example, if @var{name} is @code{(a b 2 c)}, that means to find
|
||||
field @code{c} in the third element of subfield @code{b} of field
|
||||
@code{a}. (This corresponds to @code{struct.a.b[2].c} in C.)
|
||||
For example, @w{@code{(bindat-get-field @var{struct} a b 2 c)}} means
|
||||
to find field @code{c} in the third element of subfield @code{b} of
|
||||
field @code{a}. (This corresponds to @code{@var{struct}.a.b[2].c} in
|
||||
the C programming language syntax.)
|
||||
@end defun
|
||||
|
||||
Although packing and unpacking operations change the organization of
|
||||
|
|
@ -3580,13 +3512,13 @@ both pieces of information contribute to its calculation. Likewise, the
|
|||
length of a string or array being unpacked may be longer than the data's
|
||||
total length as described by the specification.
|
||||
|
||||
@defun bindat-length spec struct
|
||||
@defun bindat-length type struct
|
||||
This function returns the total length of the data in @var{struct},
|
||||
according to @var{spec}.
|
||||
according to @var{type}.
|
||||
@end defun
|
||||
|
||||
@defun bindat-pack spec struct &optional raw idx
|
||||
This function returns a byte array packed according to @var{spec} from
|
||||
@defun bindat-pack type struct &optional raw idx
|
||||
This function returns a byte array packed according to @var{type} from
|
||||
the data in the alist @var{struct}. It normally creates and fills a
|
||||
new byte array starting at the beginning. However, if @var{raw}
|
||||
is non-@code{nil}, it specifies a pre-allocated unibyte string or vector to
|
||||
|
|
@ -3607,3 +3539,74 @@ dotted notation.
|
|||
@result{} "127.0.0.1"
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
@node Bindat Computed Types
|
||||
@subsection Advanced data layout specifications
|
||||
@cindex bindat computed types
|
||||
|
||||
Bindat type expressions are not limited to the types described
|
||||
earlier. They can also be arbitrary Lisp forms returning Bindat
|
||||
type expressions. For example, the type below describes data which
|
||||
can either contain a 24-bit error code or a vector of bytes:
|
||||
|
||||
@example
|
||||
(bindat-type
|
||||
(len u8)
|
||||
(payload . (if (zerop len) (uint 24) (vec (1- len)))))
|
||||
@end example
|
||||
|
||||
@cindex bindat packing and unpacking into arbitrary types
|
||||
Furthermore, while composite types are normally unpacked to (and
|
||||
packed from) association lists, this can be changed via the use of
|
||||
the following special keyword arguments:
|
||||
|
||||
@table @code
|
||||
@item :unpack-val @var{exp}
|
||||
When the list of fields ends with this keyword argument, then the value
|
||||
returned when unpacking is the value of @var{exp} instead of the
|
||||
standard alist. @var{exp} can refer to all the previous fields by
|
||||
their name.
|
||||
|
||||
@item :pack-val @var{exp}
|
||||
If a field's type is followed by this keyword argument, then the value
|
||||
packed into this field is returned by @var{exp} instead of being
|
||||
extracted from the alist.
|
||||
|
||||
@item :pack-var @var{name}
|
||||
If the list of fields is preceded by this keyword argument, then all
|
||||
the subsequent @code{:pack-val} arguments can refer to the overall
|
||||
value to pack into this composite type via the variable named
|
||||
@var{name}.
|
||||
@end table
|
||||
|
||||
For example, one could describe a 16-bit signed integer as follows:
|
||||
|
||||
@example
|
||||
(defconst sint16-bindat-spec
|
||||
(let* ((max (ash 1 15))
|
||||
(wrap (+ max max)))
|
||||
(bindat-type :pack-var v
|
||||
(n uint 16 :pack-val (if (< v 0) (+ v wrap) v))
|
||||
:unpack-val (if (>= n max) (- n wrap) n))))
|
||||
@end example
|
||||
|
||||
Which would then behave as follows:
|
||||
@example
|
||||
(bindat-pack sint16-bindat-spec -8)
|
||||
@result{} "\377\370"
|
||||
|
||||
(bindat-unpack sint16-bindat-spec "\300\100")
|
||||
@result{} -16320
|
||||
@end example
|
||||
|
||||
@cindex define new bindat type forms
|
||||
@cindex bindat, define new type forms
|
||||
Finally, you can define new Bindat type forms to use in Bindat type
|
||||
expressions with @code{bindat-defmacro}:
|
||||
|
||||
@defmac bindat-defmacro name args &rest body
|
||||
Define a new Bindat type expression named @var{name} and taking
|
||||
arguments @var{args}. Its behavior follows that of @code{defmacro},
|
||||
which the important difference that the new forms can only be used
|
||||
within Bindat type expressions.
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ example, it is our convention to have commands that list objects named
|
|||
as @samp{list-@var{something}}, e.g., a package called @samp{frob}
|
||||
could have a command @samp{list-frobs}, when its other global symbols
|
||||
begin with @samp{frob-}. Also, constructs that define functions,
|
||||
variables, etc., work better if they start with @samp{defun} or
|
||||
@samp{defvar}, so put the name prefix later on in the name.
|
||||
variables, etc., work better if they start with @samp{define-}, so put
|
||||
the name prefix later on in the name.
|
||||
|
||||
This recommendation applies even to names for traditional Lisp
|
||||
primitives that are not primitives in Emacs Lisp---such as
|
||||
|
|
|
|||
|
|
@ -82,11 +82,27 @@ INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32)
|
|||
## because the info files are pre-built in release tarfiles.
|
||||
INFO_TARGETS = $(INFO_COMMON) efaq-w32
|
||||
|
||||
## Some manuals have their source in .org format.
|
||||
## This is discouraged because the .texi files it generates
|
||||
## are not as well formatted as handwritten ones.
|
||||
ORG_SETUP = $(wildcard ${srcdir}/*-setup.org)
|
||||
ORG_SRC = $(filter-out ${ORG_SETUP},$(wildcard ${srcdir}/*.org))
|
||||
TEXI_FROM_ORG = ${ORG_SRC:.org=.texi}
|
||||
|
||||
# There are some naming differences between the info targets and the other
|
||||
# targets, so let's resolve them here.
|
||||
TARGETS_1 = $(INFO_INSTALL:ccmode=cc-mode)
|
||||
TARGETS = $(TARGETS_1:info.info=info)
|
||||
|
||||
texi_sources = $(addsuffix .texi,${TARGETS})
|
||||
texi_notgen = $(filter-out $(notdir ${TEXI_FROM_ORG}),${texi_sources})
|
||||
texi_and_org = $(notdir ${ORG_SRC}) ${texi_notgen}
|
||||
SOURCES = $(sort ${texi_and_org})
|
||||
.PHONY: echo-sources
|
||||
## Used by the top-level Makefile.
|
||||
echo-sources:
|
||||
@echo ${SOURCES}
|
||||
|
||||
DVI_TARGETS = $(TARGETS:=.dvi)
|
||||
HTML_TARGETS = $(TARGETS:=.html)
|
||||
PDF_TARGETS = $(TARGETS:=.pdf)
|
||||
|
|
@ -221,6 +237,30 @@ gnus.pdf: $(gnus_deps)
|
|||
${buildinfodir}/tramp.info tramp.html: ${srcdir}/trampver.texi
|
||||
|
||||
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
EMACS = ${abs_top_builddir}/src/emacs
|
||||
emacs = "${EMACS}" -batch --no-site-file --no-site-lisp
|
||||
|
||||
# Generated .texi files go in srcdir so they can be included in the
|
||||
# release tarfile along with the others.
|
||||
# Work in srcdir (and use abs_top_builddir) so that +setupfile and
|
||||
# things like org-setup's "version" macro work. Sigh.
|
||||
define org_template
|
||||
$(1:.org=.texi): $(1)
|
||||
$${AM_V_GEN}cd "$${srcdir}" && $${emacs} -l ox-texinfo \
|
||||
-f org-texinfo-export-to-texinfo-batch $$(notdir $$<) $$(notdir $$@)
|
||||
endef
|
||||
|
||||
$(foreach orgfile,${ORG_SRC},$(eval $(call org_template,$(orgfile))))
|
||||
|
||||
## foo.org depends on foo-setup.org, if the latter exists.
|
||||
define org_setup_template
|
||||
$(1:-setup.org=.texi): $(1)
|
||||
endef
|
||||
|
||||
$(foreach orgfile,${ORG_SETUP},$(eval $(call org_setup_template,$(orgfile))))
|
||||
|
||||
|
||||
.PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean
|
||||
|
||||
mostlyclean:
|
||||
|
|
@ -245,7 +285,12 @@ infoclean:
|
|||
$(buildinfodir)/$${file}-[1-9][0-9]; \
|
||||
done
|
||||
|
||||
bootstrap-clean maintainer-clean: distclean infoclean
|
||||
.PHONY: orgclean
|
||||
|
||||
orgclean:
|
||||
rm -f ${TEXI_FROM_ORG}
|
||||
|
||||
bootstrap-clean maintainer-clean: distclean infoclean orgclean
|
||||
|
||||
.PHONY: install-dvi install-html install-pdf install-ps install-doc
|
||||
|
||||
|
|
|
|||
|
|
@ -6612,7 +6612,8 @@ further discussion of infinite and indeterminate values.
|
|||
@subsection Modes Tutorial Exercise 1
|
||||
|
||||
@noindent
|
||||
Calc always stores its numbers in decimal, so even though one-third has
|
||||
Calc always stores its floating-point numbers in decimal,
|
||||
so even though one-third has
|
||||
an exact base-3 representation (@samp{3#0.1}), it is still stored as
|
||||
0.3333333 (chopped off after 12 or however many decimal digits) inside
|
||||
the calculator's memory. When this inexact number is converted back
|
||||
|
|
@ -18888,9 +18889,7 @@ Each possible value @expr{N} appears with equal probability.
|
|||
|
||||
With no numeric prefix argument, the @kbd{k r} command takes its argument
|
||||
from the stack instead. Once again, if this is a positive integer @expr{M}
|
||||
the result is a random integer less than @expr{M}. However, note that
|
||||
while numeric prefix arguments are limited to six digits or so, an @expr{M}
|
||||
taken from the stack can be arbitrarily large. If @expr{M} is negative,
|
||||
the result is a random integer less than @expr{M}. If @expr{M} is negative,
|
||||
the result is a random integer in the range
|
||||
@texline @math{M < N \le 0}.
|
||||
@infoline @expr{M < N <= 0}.
|
||||
|
|
@ -32240,7 +32239,7 @@ as the value of a function. You can use @code{return} anywhere
|
|||
inside the body of the function.
|
||||
@end itemize
|
||||
|
||||
Non-integer numbers (and extremely large integers) cannot be included
|
||||
Non-integer numbers cannot be included
|
||||
directly into a @code{defmath} definition. This is because the Lisp
|
||||
reader will fail to parse them long before @code{defmath} ever gets control.
|
||||
Instead, use the notation, @samp{:"3.1415"}. In fact, any algebraic
|
||||
|
|
@ -32374,7 +32373,7 @@ This expands to the pair of definitions,
|
|||
|
||||
@noindent
|
||||
where in this case the latter function would never really be used! Note
|
||||
that since the Calculator stores small integers as plain Lisp integers,
|
||||
that since the Calculator stores integers as plain Lisp integers,
|
||||
the @code{math-add} function will work just as well as the native
|
||||
@code{+} even when the intent is to operate on native Lisp integers.
|
||||
|
||||
|
|
@ -32643,8 +32642,8 @@ Like @samp{integer}, but the argument must be non-negative.
|
|||
|
||||
@item fixnum
|
||||
@findex fixnum
|
||||
Like @samp{integer}, but the argument must fit into a native Lisp integer,
|
||||
which on most systems means less than 2^23 in absolute value. The
|
||||
Like @samp{integer}, but the argument must fit into a native Lisp fixnum,
|
||||
which on most systems means less than 2^61 in absolute value. The
|
||||
argument is converted into Lisp-integer form if necessary.
|
||||
|
||||
@item float
|
||||
|
|
@ -32740,50 +32739,6 @@ Emacs Lisp function:
|
|||
count))
|
||||
@end smallexample
|
||||
|
||||
If the input numbers are large, this function involves a fair amount
|
||||
of arithmetic. A binary right shift is essentially a division by two;
|
||||
recall that Calc stores integers in decimal form so bit shifts must
|
||||
involve actual division.
|
||||
|
||||
To gain a bit more efficiency, we could divide the integer into
|
||||
@var{n}-bit chunks, each of which can be handled quickly because
|
||||
they fit into Lisp integers. It turns out that Calc's arithmetic
|
||||
routines are especially fast when dividing by an integer less than
|
||||
1000, so we can set @var{n = 9} bits and use repeated division by 512:
|
||||
|
||||
@smallexample
|
||||
(defmath bcount ((natnum n))
|
||||
(interactive 1 "bcnt")
|
||||
(let ((count 0))
|
||||
(while (not (fixnump n))
|
||||
(let ((qr (idivmod n 512)))
|
||||
(setq count (+ count (bcount-fixnum (cdr qr)))
|
||||
n (car qr))))
|
||||
(+ count (bcount-fixnum n))))
|
||||
|
||||
(defun bcount-fixnum (n)
|
||||
(let ((count 0))
|
||||
(while (> n 0)
|
||||
(setq count (+ count (logand n 1))
|
||||
n (ash n -1)))
|
||||
count))
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
Note that the second function uses @code{defun}, not @code{defmath}.
|
||||
Because this function deals only with native Lisp integers (``fixnums''),
|
||||
it can use the actual Emacs @code{+} and related functions rather
|
||||
than the slower but more general Calc equivalents which @code{defmath}
|
||||
uses.
|
||||
|
||||
The @code{idivmod} function does an integer division, returning both
|
||||
the quotient and the remainder at once. Again, note that while it
|
||||
might seem that @samp{(logand n 511)} and @samp{(ash n -9)} are
|
||||
more efficient ways to split off the bottom nine bits of @code{n},
|
||||
actually they are less efficient because each operation is really
|
||||
a division by 512 in disguise; @code{idivmod} allows us to do the
|
||||
same thing with a single division by 512.
|
||||
|
||||
@node Sine Example, , Bit Counting Example, Example Definitions
|
||||
@subsubsection The Sine Function
|
||||
|
||||
|
|
@ -33042,9 +32997,7 @@ in this case it would be easier to call the low-level @code{math-add}
|
|||
function in Calc, if you can remember its name.
|
||||
|
||||
In particular, note that a plain Lisp integer is acceptable to Calc
|
||||
as a raw object. (All Lisp integers are accepted on input, but
|
||||
integers of more than six decimal digits are converted to ``big-integer''
|
||||
form for output. @xref{Data Type Formats}.)
|
||||
as a raw object.
|
||||
|
||||
When it comes time to display the object, just use @samp{(calc-eval a)}
|
||||
to format it as a string.
|
||||
|
|
@ -33308,31 +33261,11 @@ you can't prove this file will already be loaded.
|
|||
@subsubsection Data Type Formats
|
||||
|
||||
@noindent
|
||||
Integers are stored in either of two ways, depending on their magnitude.
|
||||
Integers less than one million in absolute value are stored as standard
|
||||
Lisp integers. This is the only storage format for Calc data objects
|
||||
which is not a Lisp list.
|
||||
|
||||
Large integers are stored as lists of the form @samp{(bigpos @var{d0}
|
||||
@var{d1} @var{d2} @dots{})} for sufficiently large positive integers
|
||||
(where ``sufficiently large'' depends on the machine), or
|
||||
@samp{(bigneg @var{d0} @var{d1} @var{d2} @dots{})} for negative
|
||||
integers. Each @var{d} is a base-@expr{10^n} ``digit'' (where again,
|
||||
@expr{n} depends on the machine), a Lisp integer from 0 to
|
||||
99@dots{}9. The least significant digit is @var{d0}; the last digit,
|
||||
@var{dn}, which is always nonzero, is the most significant digit. For
|
||||
example, the integer @mathit{-12345678} might be stored as
|
||||
@samp{(bigneg 678 345 12)}.
|
||||
|
||||
The distinction between small and large integers is entirely hidden from
|
||||
the user. In @code{defmath} definitions, the Lisp predicate @code{integerp}
|
||||
returns true for either kind of integer, and in general both big and small
|
||||
integers are accepted anywhere the word ``integer'' is used in this manual.
|
||||
If the distinction must be made, native Lisp integers are called @dfn{fixnums}
|
||||
and large integers are called @dfn{bignums}.
|
||||
Integers are stored as standard Lisp integers. This is the only
|
||||
storage format for Calc data objects which is not a Lisp list.
|
||||
|
||||
Fractions are stored as a list of the form, @samp{(frac @var{n} @var{d})}
|
||||
where @var{n} is an integer (big or small) numerator, @var{d} is an
|
||||
where @var{n} is an integer numerator, @var{d} is an
|
||||
integer denominator greater than one, and @var{n} and @var{d} are relatively
|
||||
prime. Note that fractions where @var{d} is one are automatically converted
|
||||
to plain integers by all math routines; fractions where @var{d} is negative
|
||||
|
|
@ -33341,7 +33274,7 @@ are normalized by negating the numerator and denominator.
|
|||
Floating-point numbers are stored in the form, @samp{(float @var{mant}
|
||||
@var{exp})}, where @var{mant} (the ``mantissa'') is an integer less than
|
||||
@samp{10^@var{p}} in absolute value (@var{p} represents the current
|
||||
precision), and @var{exp} (the ``exponent'') is a fixnum. The value of
|
||||
precision), and @var{exp} (the ``exponent'') is an integer. The value of
|
||||
the float is @samp{@var{mant} * 10^@var{exp}}. For example, the number
|
||||
@mathit{-3.14} is stored as @samp{(float -314 -2) = -314*10^-2}. Other constraints
|
||||
are that the number 0.0 is always stored as @samp{(float 0 0)}, and,
|
||||
|
|
@ -33736,7 +33669,7 @@ Returns true if @var{x} is an integer of any size.
|
|||
@end defun
|
||||
|
||||
@defun fixnump x
|
||||
Returns true if @var{x} is a native Lisp integer.
|
||||
Returns true if @var{x} is a native Lisp fixnum.
|
||||
@end defun
|
||||
|
||||
@defun natnump x
|
||||
|
|
@ -33744,7 +33677,7 @@ Returns true if @var{x} is a nonnegative integer of any size.
|
|||
@end defun
|
||||
|
||||
@defun fixnatnump x
|
||||
Returns true if @var{x} is a nonnegative Lisp integer.
|
||||
Returns true if @var{x} is a nonnegative Lisp fixnum.
|
||||
@end defun
|
||||
|
||||
@defun num-integerp x
|
||||
|
|
@ -33899,7 +33832,7 @@ converted to @samp{(math-equal x y)}.
|
|||
|
||||
@defun equal-int x n
|
||||
Returns true if @var{x} and @var{n} are numerically equal, where @var{n}
|
||||
is a fixnum which is not a multiple of 10. This will automatically be
|
||||
is an integer which is not a multiple of 10. This will automatically be
|
||||
used by @code{defmath} in place of the more general @code{math-equal}
|
||||
whenever possible.
|
||||
@end defun
|
||||
|
|
@ -33980,12 +33913,8 @@ respectively, instead.
|
|||
|
||||
@defun normalize val
|
||||
(Full form: @code{math-normalize}.)
|
||||
Reduce the value @var{val} to standard form. For example, if @var{val}
|
||||
is a fixnum, it will be converted to a bignum if it is too large, and
|
||||
if @var{val} is a bignum it will be normalized by clipping off trailing
|
||||
(i.e., most-significant) zero digits and converting to a fixnum if it is
|
||||
small. All the various data types are similarly converted to their standard
|
||||
forms. Variables are left alone, but function calls are actually evaluated
|
||||
Reduce the value @var{val} to standard form.
|
||||
Variables are left alone, but function calls are actually evaluated
|
||||
in formulas. For example, normalizing @samp{(+ 2 (calcFunc-abs -4))} will
|
||||
return 6.
|
||||
|
||||
|
|
@ -34098,9 +34027,9 @@ integer rather than truncating.
|
|||
@end defun
|
||||
|
||||
@defun fixnum n
|
||||
Return the integer @var{n} as a fixnum, i.e., a native Lisp integer.
|
||||
If @var{n} is outside the permissible range for Lisp integers (usually
|
||||
24 binary bits) the result is undefined.
|
||||
Return the integer @var{n} as a fixnum, i.e., a small Lisp integer.
|
||||
If @var{n} is outside the permissible range for Lisp fixnums (usually
|
||||
62 binary bits) the result is undefined.
|
||||
@end defun
|
||||
|
||||
@defun sqr x
|
||||
|
|
|
|||
3303
doc/misc/modus-themes.org
Normal file
3303
doc/misc/modus-themes.org
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
53
doc/misc/org-setup.org
Normal file
53
doc/misc/org-setup.org
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# SETUPFILE for Org manual
|
||||
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Emacs.
|
||||
#
|
||||
# GNU Emacs is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GNU Emacs is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# XXX: We cannot use TODO keyword as a node starts with "TODO".
|
||||
#+todo: REVIEW FIXME | DONE
|
||||
#+property: header-args :eval no
|
||||
#+startup: overview nologdone
|
||||
|
||||
# Use proper quote and backtick for code sections in PDF output
|
||||
# Cf. Texinfo manual 14.2
|
||||
#+texinfo_header: @set txicodequoteundirected
|
||||
#+texinfo_header: @set txicodequotebacktick
|
||||
|
||||
# Contact Info
|
||||
#+texinfo_header: @set MAINTAINERSITE @uref{https://orgmode.org,maintainers webpage}
|
||||
#+texinfo_header: @set MAINTAINER Bastien Guerry
|
||||
#+texinfo_header: @set MAINTAINEREMAIL @email{bzg@gnu.org}
|
||||
#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:bzg@gnu.org,contact the maintainer}
|
||||
|
||||
#+options: H:4 num:t toc:t author:t \n:nil ::t |:t ^:nil -:t f:t *:t <:t e:t ':t
|
||||
#+options: d:nil todo:nil pri:nil tags:not-in-toc stat:nil broken-links:mark
|
||||
#+select_tags: export
|
||||
#+exclude_tags: noexport
|
||||
|
||||
#+macro: cite @@texinfo:@cite{@@$1@@texinfo:}@@
|
||||
#+macro: var @@texinfo:@var{@@$1@@texinfo:}@@
|
||||
|
||||
# The "version" macro extracts "Version" keyword from "org.el". It
|
||||
# returns major.minor version number. This is sufficient since bugfix
|
||||
# releases are not expected to add features and therefore imply manual
|
||||
# modifications.
|
||||
#+macro: version (eval (with-current-buffer (find-file-noselect "../../lisp/org/org.el") (org-with-point-at 1 (if (re-search-forward "Version: +\\([0-9.]+\\)" nil t) (mapconcat #'identity (cl-subseq (split-string (match-string-no-properties 1) "\\.") 0 2) ".") (error "Missing \"Version\" keyword in \"org.el\"")))))
|
||||
|
||||
# The "kbd" macro turns KBD into @kbd{KBD}. Additionally, it
|
||||
# encloses case-sensitive special keys (SPC, RET...) within @key{...}.
|
||||
#+macro: kbd (eval (let ((case-fold-search nil) (regexp (regexp-opt '("SPC" "RET" "LFD" "TAB" "BS" "ESC" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN") 'words))) (format "@@texinfo:@kbd{@@%s@@texinfo:}@@" (replace-regexp-in-string regexp "@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t))))
|
||||
|
||||
21904
doc/misc/org.org
Normal file
21904
doc/misc/org.org
Normal file
File diff suppressed because it is too large
Load diff
23148
doc/misc/org.texi
23148
doc/misc/org.texi
File diff suppressed because it is too large
Load diff
|
|
@ -2211,7 +2211,7 @@ be recomputed. To force @value{tramp} to recompute afresh, call
|
|||
|
||||
By default, @value{tramp} uses the command @command{/bin/sh} for
|
||||
starting a shell on the remote host. This can be changed by setting
|
||||
the connection property @t{"remote-shell"}; see @pxref{Predefined
|
||||
the connection property @t{"remote-shell"}; see @ref{Predefined
|
||||
connection information}. If you want, for example, use
|
||||
@command{/usr/bin/zsh} on a remote host, you might apply
|
||||
|
||||
|
|
|
|||
102
etc/NEWS
102
etc/NEWS
|
|
@ -71,6 +71,12 @@ shaping, so 'configure' now recommends that combination.
|
|||
** The ftx font backend driver has been removed.
|
||||
It was declared obsolete in Emacs 27.1.
|
||||
|
||||
---
|
||||
** The configure option '--without-makeinfo' has been removed.
|
||||
This was only ever relevant when building from a repository checkout.
|
||||
Please install makeinfo, or if all else fails run 'make lisp' instead
|
||||
of 'make [all]'.
|
||||
|
||||
---
|
||||
** Support for building with '-fcheck-pointer-bounds' has been removed.
|
||||
GCC has withdrawn the '-fcheck-pointer-bounds' option and support for
|
||||
|
|
@ -310,10 +316,12 @@ Additionally, the function now accepts a HIST argument which can be
|
|||
used to specify a custom history variable.
|
||||
|
||||
+++
|
||||
** Input history for 'goto-line' is now local to every buffer.
|
||||
Each buffer will keep a separate history of line numbers used with
|
||||
'goto-line'. This should help making faster the process of finding
|
||||
line numbers that were previously jumped to.
|
||||
** Input history for 'goto-line' can now be made local to every buffer.
|
||||
In any event, line numbers used with 'goto-line' are kept in their own
|
||||
history list. This should help make faster the process of finding
|
||||
line numbers that were previously jumped to. By default, all buffers
|
||||
share a single history list. To make every buffer have its own
|
||||
history list, customize the user option 'goto-line-history-local'.
|
||||
|
||||
+++
|
||||
** New command 'goto-line-relative' to use in a narrowed buffer.
|
||||
|
|
@ -357,19 +365,28 @@ trying to be non-destructive.
|
|||
This command opens a new buffer called "*Memory Report*" and gives a
|
||||
summary of where Emacs is using memory currently.
|
||||
|
||||
+++
|
||||
** The history list for the 'goto-line' command is now a single list
|
||||
for all buffers by default. You can configure a separate list for
|
||||
each buffer by customizing the user option 'goto-line-history-local'.
|
||||
|
||||
** Outline
|
||||
|
||||
+++
|
||||
*** New commands to cycle heading visibility.
|
||||
Typing 'TAB' on a heading cycles the current section between "hide
|
||||
all", "subheadings", and "show all" state. Typing 'S-TAB' anywhere in
|
||||
the buffer cycles the whole buffer between "only top-level headings",
|
||||
"all headings and subheadings", and "show all" states.
|
||||
Typing 'TAB' on a heading line cycles the current section between
|
||||
"hide all", "subheadings", and "show all" states. Typing 'S-TAB'
|
||||
anywhere in the buffer cycles the whole buffer between "only top-level
|
||||
headings", "all headings and subheadings", and "show all" states.
|
||||
|
||||
*** New minor mode 'outline-cycle-minor-mode'.
|
||||
This mode is a variant of 'outline-minor-mode', with the difference
|
||||
that 'TAB' and 'S-TAB' on heading lines cycle heading visibility.
|
||||
Typing 'TAB' on a heading line cycles the current section between
|
||||
"hide all", "subheadings", and "show all" states. Typing 'S-TAB' on a
|
||||
heading line cycles the whole buffer between "only top-level
|
||||
headings", "all headings and subheadings", and "show all" states.
|
||||
|
||||
*** New minor mode 'outline-cycle-highlight-minor-mode'.
|
||||
This mode is a variant of 'outline-cycle-minor-mode'. It puts
|
||||
highlighting on heading lines using standard outline faces. This
|
||||
works well only when there are no conflicts with faces used by the
|
||||
major mode.
|
||||
|
||||
|
||||
* Changes in Specialized Modes and Packages in Emacs 28.1
|
||||
|
|
@ -379,6 +396,10 @@ the buffer cycles the whole buffer between "only top-level headings",
|
|||
*** New function 'macroexp-file-name' to know the name of the current file
|
||||
---
|
||||
*** New function 'macroexp-compiling-p' to know if we're compiling.
|
||||
---
|
||||
*** New function 'macroexp-warn-and-return' to help emit warnings.
|
||||
This used to be named 'macroexp--warn-and-return' and has proved useful
|
||||
and well-behaved enough to lose the "internal" marker.
|
||||
|
||||
** 'blink-cursor-mode' is now enabled by default regardless of the UI.
|
||||
It used to be enabled when Emacs is started in GUI mode but not when started
|
||||
|
|
@ -386,11 +407,19 @@ in text mode. The cursor still only actually blinks in GUI frames.
|
|||
|
||||
** Bindat
|
||||
+++
|
||||
*** New types 'u64' and 'u64r'
|
||||
+++
|
||||
*** New macro 'bindat-spec' to define specs, with Edebug support
|
||||
*** New 'Bindat type expression' description language.
|
||||
This new system is provided by the new macro 'bindat-type' and
|
||||
obsoletes the old data layout specifications. It supports
|
||||
arbitrary-size integers, recursive types, and more. See the Info node
|
||||
'Byte Packing' in the ELisp manual for more details.
|
||||
|
||||
** pcase
|
||||
|
||||
+++
|
||||
*** The 'or' pattern now binds the union of the vars of its sub-patterns
|
||||
If a variable is not bound by the subpattern that matched, it gets bound
|
||||
to nil. This was already sometimes the case, but it is now guaranteed.
|
||||
|
||||
+++
|
||||
*** The 'pred' pattern can now take the form '(pred (not FUN))'.
|
||||
This is like '(pred (lambda (x) (not (FUN x))))' but results
|
||||
|
|
@ -494,6 +523,13 @@ value of 'tab-bar-show'.
|
|||
It can be used to enable/disable the tab bar individually on each frame
|
||||
independently from the value of 'tab-bar-mode' and 'tab-bar-show'.
|
||||
|
||||
---
|
||||
*** New variable 'tab-bar-format' defines a list of tab bar items.
|
||||
When it contains 'tab-bar-format-global' (possibly appended after
|
||||
'tab-bar-format-align-right'), then after enabling 'display-time-mode'
|
||||
(or any other mode that uses 'global-mode-string') it displays time
|
||||
aligned to the right on the tab bar instead of the mode line.
|
||||
|
||||
---
|
||||
*** 'Mod-9' bound to 'tab-last' now switches to the last tab.
|
||||
It also supports a negative argument.
|
||||
|
|
@ -1135,8 +1171,18 @@ effect.
|
|||
A pattern like '(map :sym)' binds the map's value for ':sym' to 'sym',
|
||||
equivalent to '(map (:sym sym))'.
|
||||
|
||||
---
|
||||
*** The function 'map-copy' now uses 'copy-alist' on alists.
|
||||
This is a slightly deeper copy than the previous 'copy-sequence'.
|
||||
|
||||
---
|
||||
*** The function 'map-contains-key' now supports plists.
|
||||
|
||||
** Package
|
||||
|
||||
+++
|
||||
*** New command 'package-browse-url' and keystroke 'w'.
|
||||
|
||||
+++
|
||||
*** New commands to filter the package list.
|
||||
The filter commands are bound to the following keys:
|
||||
|
|
@ -1532,6 +1578,16 @@ component are now rejected by 'json-read' and friends. This makes
|
|||
them more compliant with the JSON specification and consistent with
|
||||
the native JSON parsing functions.
|
||||
|
||||
---
|
||||
*** Some JSON encoding functions are now obsolete.
|
||||
The functions 'json-encode-number', 'json-encode-hash-table',
|
||||
'json-encode-key', and 'json-encode-list' are now obsolete.
|
||||
|
||||
The first two are kept as aliases of 'json-encode', which should be
|
||||
used instead. Uses of 'json-encode-list' should be changed to call
|
||||
one of 'json-encode', 'json-encode-alist', 'json-encode-plist', or
|
||||
'json-encode-array' instead.
|
||||
|
||||
** xml.el
|
||||
|
||||
*** XML serialization functions now reject invalid characters.
|
||||
|
|
@ -2259,7 +2315,10 @@ This is no longer supported, and setting this variable has no effect.
|
|||
Use macro 'with-current-buffer-window' with action alist entry 'body-function'.
|
||||
|
||||
---
|
||||
** The metamail.el library is now marked obsolete.
|
||||
** The inversion.el library is now obsolete.
|
||||
|
||||
---
|
||||
** The metamail.el library is now obsolete.
|
||||
|
||||
---
|
||||
** Some obsolete variable and function aliases in dbus.el have been removed.
|
||||
|
|
@ -2396,6 +2455,9 @@ This can be used to control whether the defined mode is a command
|
|||
or not, and is useful when defining commands that aren't meant to be
|
||||
used by users directly.
|
||||
|
||||
---
|
||||
** The 'easymenu' library is now preloaded.
|
||||
|
||||
** The 'values' variable is now obsolete.
|
||||
|
||||
---
|
||||
|
|
@ -2508,6 +2570,12 @@ region's (or buffer's) end.
|
|||
This function can be used by modes to add elements to the
|
||||
'choice' customization type of a variable.
|
||||
|
||||
+++
|
||||
** New function 'require-theme'.
|
||||
This function is like 'require', but searches 'custom-theme-load-path'
|
||||
instead of 'load-path'. It can be used by Custom themes to load
|
||||
supporting Lisp files when 'require' is unsuitable.
|
||||
|
||||
+++
|
||||
** New function 'file-modes-number-to-symbolic' to convert a numeric
|
||||
file mode specification into symbolic form.
|
||||
|
|
|
|||
|
|
@ -692,3 +692,9 @@ COPYING PERMISSIONS:
|
|||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
;;; Local Variables:
|
||||
;;; outline-regexp: "\\*\\_>"
|
||||
;;; eval: (outline-cycle-highlight-minor-mode)
|
||||
;;; End:
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ grep -nH -e "xyzxyz" ../info/*
|
|||
../info/emacs-2 1205 inserts `xyzxyzxyzxyz' in the current buffer.
|
||||
|
||||
|
||||
* Miscellaneous
|
||||
|
||||
Copyright (C) 2005-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -124,4 +125,5 @@ COPYING PERMISSIONS:
|
|||
;;; Local Variables:
|
||||
;;; eval: (let ((inhibit-read-only t) (compilation-filter-start (point-min))) (save-excursion (goto-char (point-max)) (grep-filter) (set-buffer-modified-p nil)))
|
||||
;;; buffer-read-only: t
|
||||
;;; eval: (outline-cycle-highlight-minor-mode)
|
||||
;;; End:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
6442
etc/themes/modus-themes.el
Normal file
6442
etc/themes/modus-themes.el
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -75,9 +75,6 @@
|
|||
(declare-function epa-passphrase-callback-function
|
||||
"epa" (context key-id handback))
|
||||
|
||||
;;;_* Dependency loads
|
||||
(require 'overlay)
|
||||
|
||||
;;;_* USER CUSTOMIZATION VARIABLES:
|
||||
|
||||
;;;_ > defgroup allout, allout-keybindings
|
||||
|
|
|
|||
|
|
@ -117,8 +117,7 @@ This is set by the prefix argument to `buffer-menu' and related
|
|||
commands.")
|
||||
|
||||
(defvar Buffer-menu-mode-map
|
||||
(let ((map (make-sparse-keymap))
|
||||
(menu-map (make-sparse-keymap)))
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map tabulated-list-mode-map)
|
||||
(define-key map "v" 'Buffer-menu-select)
|
||||
(define-key map "2" 'Buffer-menu-2-window)
|
||||
|
|
@ -152,82 +151,63 @@ commands.")
|
|||
|
||||
(define-key map [mouse-2] 'Buffer-menu-mouse-select)
|
||||
(define-key map [follow-link] 'mouse-face)
|
||||
|
||||
(define-key map [menu-bar Buffer-menu-mode] (cons (purecopy "Buffer-Menu") menu-map))
|
||||
(bindings--define-key menu-map [quit]
|
||||
'(menu-item "Quit" quit-window
|
||||
:help "Remove the buffer menu from the display"))
|
||||
(bindings--define-key menu-map [rev]
|
||||
'(menu-item "Refresh" revert-buffer
|
||||
:help "Refresh the *Buffer List* buffer contents"))
|
||||
(bindings--define-key menu-map [s0] menu-bar-separator)
|
||||
(bindings--define-key menu-map [tf]
|
||||
'(menu-item "Show Only File Buffers" Buffer-menu-toggle-files-only
|
||||
:button (:toggle . Buffer-menu-files-only)
|
||||
:help "Toggle whether the current buffer-menu displays only file buffers"))
|
||||
(bindings--define-key menu-map [s1] menu-bar-separator)
|
||||
;; FIXME: The "Select" entries could use better names...
|
||||
(bindings--define-key menu-map [sel]
|
||||
'(menu-item "Select Marked" Buffer-menu-select
|
||||
:help "Select this line's buffer; also display buffers marked with `>'"))
|
||||
(bindings--define-key menu-map [bm2]
|
||||
'(menu-item "Select Two" Buffer-menu-2-window
|
||||
:help "Select this line's buffer, with previous buffer in second window"))
|
||||
(bindings--define-key menu-map [bm1]
|
||||
'(menu-item "Select Current" Buffer-menu-1-window
|
||||
:help "Select this line's buffer, alone, in full frame"))
|
||||
(bindings--define-key menu-map [ow]
|
||||
'(menu-item "Select in Other Window" Buffer-menu-other-window
|
||||
:help "Select this line's buffer in other window, leaving buffer menu visible"))
|
||||
(bindings--define-key menu-map [tw]
|
||||
'(menu-item "Select in Current Window" Buffer-menu-this-window
|
||||
:help "Select this line's buffer in this window"))
|
||||
(bindings--define-key menu-map [s2] menu-bar-separator)
|
||||
(bindings--define-key menu-map [is]
|
||||
'(menu-item "Regexp Isearch Marked Buffers..." Buffer-menu-isearch-buffers-regexp
|
||||
:help "Search for a regexp through all marked buffers using Isearch"))
|
||||
(bindings--define-key menu-map [ir]
|
||||
'(menu-item "Isearch Marked Buffers..." Buffer-menu-isearch-buffers
|
||||
:help "Search for a string through all marked buffers using Isearch"))
|
||||
(bindings--define-key menu-map [mo]
|
||||
'(menu-item "Multi Occur Marked Buffers..." Buffer-menu-multi-occur
|
||||
:help "Show lines matching a regexp in marked buffers using Occur"))
|
||||
(bindings--define-key menu-map [s3] menu-bar-separator)
|
||||
(bindings--define-key menu-map [by]
|
||||
'(menu-item "Bury" Buffer-menu-bury
|
||||
:help "Bury the buffer listed on this line"))
|
||||
(bindings--define-key menu-map [vt]
|
||||
'(menu-item "Set Unmodified" Buffer-menu-not-modified
|
||||
:help "Mark buffer on this line as unmodified (no changes to save)"))
|
||||
(bindings--define-key menu-map [ex]
|
||||
'(menu-item "Execute" Buffer-menu-execute
|
||||
:help "Save and/or delete buffers marked with s or k commands"))
|
||||
(bindings--define-key menu-map [s4] menu-bar-separator)
|
||||
(bindings--define-key menu-map [delb]
|
||||
'(menu-item "Mark for Delete and Move Backwards" Buffer-menu-delete-backwards
|
||||
:help "Mark buffer on this line to be deleted by x command and move up one line"))
|
||||
(bindings--define-key menu-map [del]
|
||||
'(menu-item "Mark for Delete" Buffer-menu-delete
|
||||
:help "Mark buffer on this line to be deleted by x command"))
|
||||
|
||||
(bindings--define-key menu-map [sv]
|
||||
'(menu-item "Mark for Save" Buffer-menu-save
|
||||
:help "Mark buffer on this line to be saved by x command"))
|
||||
(bindings--define-key menu-map [umk]
|
||||
'(menu-item "Unmark" Buffer-menu-unmark
|
||||
:help "Cancel all requested operations on buffer on this line and move down"))
|
||||
(bindings--define-key menu-map [umkab]
|
||||
'(menu-item "Remove marks..." Buffer-menu-unmark-all-buffers
|
||||
:help "Cancel a requested operation on all buffers"))
|
||||
(bindings--define-key menu-map [umka]
|
||||
'(menu-item "Unmark all" Buffer-menu-unmark-all
|
||||
:help "Cancel all requested operations on buffers"))
|
||||
(bindings--define-key menu-map [mk]
|
||||
'(menu-item "Mark" Buffer-menu-mark
|
||||
:help "Mark buffer on this line for being displayed by v command"))
|
||||
map)
|
||||
"Local keymap for `Buffer-menu-mode' buffers.")
|
||||
|
||||
(easy-menu-define Buffer-menu-mode-menu Buffer-menu-mode-map
|
||||
"Menu for `Buffer-menu-mode' buffers."
|
||||
'("Buffer-Menu"
|
||||
["Mark" Buffer-menu-mark
|
||||
:help "Mark buffer on this line for being displayed by v command"]
|
||||
["Unmark all" Buffer-menu-unmark-all
|
||||
:help "Cancel all requested operations on buffers"]
|
||||
["Remove marks..." Buffer-menu-unmark-all-buffers
|
||||
:help "Cancel a requested operation on all buffers"]
|
||||
["Unmark" Buffer-menu-unmark
|
||||
:help "Cancel all requested operations on buffer on this line and move down"]
|
||||
["Mark for Save" Buffer-menu-save
|
||||
:help "Mark buffer on this line to be saved by x command"]
|
||||
["Mark for Delete" Buffer-menu-delete
|
||||
:help "Mark buffer on this line to be deleted by x command"]
|
||||
["Mark for Delete and Move Backwards" Buffer-menu-delete-backwards
|
||||
:help "Mark buffer on this line to be deleted by x command and move up one line"]
|
||||
"---"
|
||||
["Execute" Buffer-menu-execute
|
||||
:help "Save and/or delete buffers marked with s or k commands"]
|
||||
["Set Unmodified" Buffer-menu-not-modified
|
||||
:help "Mark buffer on this line as unmodified (no changes to save)"]
|
||||
["Bury" Buffer-menu-bury
|
||||
:help "Bury the buffer listed on this line"]
|
||||
"---"
|
||||
["Multi Occur Marked Buffers..." Buffer-menu-multi-occur
|
||||
:help "Show lines matching a regexp in marked buffers using Occur"]
|
||||
["Isearch Marked Buffers..." Buffer-menu-isearch-buffers
|
||||
:help "Search for a string through all marked buffers using Isearch"]
|
||||
["Regexp Isearch Marked Buffers..." Buffer-menu-isearch-buffers-regexp
|
||||
:help "Search for a regexp through all marked buffers using Isearch"]
|
||||
"---"
|
||||
;; FIXME: The "Select" entries could use better names...
|
||||
["Select in Current Window" Buffer-menu-this-window
|
||||
:help "Select this line's buffer in this window"]
|
||||
["Select in Other Window" Buffer-menu-other-window
|
||||
:help "Select this line's buffer in other window, leaving buffer menu visible"]
|
||||
["Select Current" Buffer-menu-1-window
|
||||
:help "Select this line's buffer, alone, in full frame"]
|
||||
["Select Two" Buffer-menu-2-window
|
||||
:help "Select this line's buffer, with previous buffer in second window"]
|
||||
["Select Marked" Buffer-menu-select
|
||||
:help "Select this line's buffer; also display buffers marked with `>'"]
|
||||
"---"
|
||||
["Show Only File Buffers" Buffer-menu-toggle-files-only
|
||||
:help "Toggle whether the current buffer-menu displays only file buffers"
|
||||
:style toggle
|
||||
:selected Buffer-menu-files-only]
|
||||
"---"
|
||||
["Refresh" revert-buffer
|
||||
:help "Refresh the *Buffer List* buffer contents"]
|
||||
["Quit" quit-window
|
||||
:help "Remove the buffer menu from the display"]))
|
||||
|
||||
(define-derived-mode Buffer-menu-mode tabulated-list-mode "Buffer Menu"
|
||||
"Major mode for Buffer Menu buffers.
|
||||
The Buffer Menu is invoked by the commands \\[list-buffers],
|
||||
|
|
|
|||
|
|
@ -2565,9 +2565,9 @@ If X is not an error form, return 1."
|
|||
;;; True if A is numerically equal to the integer B. [P N S] [Public]
|
||||
;;; B must not be a multiple of 10.
|
||||
(defun math-equal-int (a b)
|
||||
(or (eq a b)
|
||||
(or (eql a b)
|
||||
(and (eq (car-safe a) 'float)
|
||||
(eq (nth 1 a) b)
|
||||
(eql (nth 1 a) b)
|
||||
(= (nth 2 a) 0))))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1985,22 +1985,37 @@ Redefine the corresponding command."
|
|||
(cons 'quote
|
||||
(math-define-lambda (nth 1 exp) math-exp-env))
|
||||
exp))
|
||||
((memq func '(let let* for foreach))
|
||||
(let ((head (nth 1 exp))
|
||||
(body (cdr (cdr exp))))
|
||||
(if (memq func '(let let*))
|
||||
()
|
||||
(setq func (cdr (assq func '((for . math-for)
|
||||
(foreach . math-foreach)))))
|
||||
(if (not (listp (car head)))
|
||||
(setq head (list head))))
|
||||
(macroexpand
|
||||
(cons func
|
||||
(cons (math-define-let head)
|
||||
(math-define-body body
|
||||
(nconc
|
||||
(math-define-let-env head)
|
||||
math-exp-env)))))))
|
||||
((eq func 'let)
|
||||
(let ((bindings (nth 1 exp))
|
||||
(body (cddr exp)))
|
||||
`(let ,(math-define-let bindings)
|
||||
,@(math-define-body
|
||||
body (append (math-define-let-env bindings)
|
||||
math-exp-env)))))
|
||||
((eq func 'let*)
|
||||
;; Rewrite in terms of `let'.
|
||||
(let ((bindings (nth 1 exp))
|
||||
(body (cddr exp)))
|
||||
(math-define-exp
|
||||
(if (> (length bindings) 1)
|
||||
`(let ,(list (car bindings))
|
||||
(let* ,(cdr bindings) ,@body))
|
||||
`(let ,bindings ,@body)))))
|
||||
((memq func '(for foreach))
|
||||
(let ((bindings (nth 1 exp))
|
||||
(body (cddr exp)))
|
||||
(if (> (length bindings) 1)
|
||||
;; Rewrite as nested loops.
|
||||
(math-define-exp
|
||||
`(,func ,(list (car bindings))
|
||||
(,func ,(cdr bindings) ,@body)))
|
||||
(let ((mac (cdr (assq func '((for . math-for)
|
||||
(foreach . math-foreach))))))
|
||||
(macroexpand
|
||||
`(,mac ,(math-define-let bindings)
|
||||
,@(math-define-body
|
||||
body (append (math-define-let-env bindings)
|
||||
math-exp-env))))))))
|
||||
((and (memq func '(setq setf))
|
||||
(math-complicated-lhs (cdr exp)))
|
||||
(if (> (length exp) 3)
|
||||
|
|
@ -2017,7 +2032,7 @@ Redefine the corresponding command."
|
|||
(math-define-cond (cdr exp))))
|
||||
((and (consp func) ; ('spam a b) == force use of plain spam
|
||||
(eq (car func) 'quote))
|
||||
(cons func (math-define-list (cdr exp))))
|
||||
(cons (cadr func) (math-define-list (cdr exp))))
|
||||
((symbolp func)
|
||||
(let ((args (math-define-list (cdr exp)))
|
||||
(prim (assq func math-prim-funcs)))
|
||||
|
|
@ -2276,20 +2291,16 @@ Redefine the corresponding command."
|
|||
|
||||
(defun math-handle-foreach (head body)
|
||||
(let ((var (nth 0 (car head)))
|
||||
(loop-var (gensym "foreach"))
|
||||
(data (nth 1 (car head)))
|
||||
(body (if (cdr head)
|
||||
(list (math-handle-foreach (cdr head) body))
|
||||
body)))
|
||||
(cons 'let
|
||||
(cons (list (list var data))
|
||||
(list
|
||||
(cons 'while
|
||||
(cons var
|
||||
(append body
|
||||
(list (list 'setq
|
||||
var
|
||||
(list 'cdr var)))))))))))
|
||||
|
||||
`(let ((,loop-var ,data))
|
||||
(while ,loop-var
|
||||
(let ((,var (car ,loop-var)))
|
||||
,@(append body
|
||||
`((setq ,loop-var (cdr ,loop-var)))))))))
|
||||
|
||||
(defun math-body-refers-to (body thing)
|
||||
(or (equal body thing)
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(declare-function inversion-check-version "inversion")
|
||||
|
||||
(defvar cedet-cscope-min-version "15.7"
|
||||
"Minimum version of CScope required.")
|
||||
|
||||
|
|
@ -139,7 +137,6 @@ If optional programmatic argument NOERROR is non-nil,
|
|||
then instead of throwing an error if CScope isn't available,
|
||||
return nil."
|
||||
(interactive)
|
||||
(require 'inversion)
|
||||
(let ((b (condition-case nil
|
||||
(cedet-cscope-call (list "-V"))
|
||||
(error nil)))
|
||||
|
|
@ -153,7 +150,7 @@ return nil."
|
|||
(goto-char (point-min))
|
||||
(re-search-forward "cscope: version \\([0-9.]+\\)" nil t)
|
||||
(setq rev (match-string 1))
|
||||
(if (inversion-check-version rev nil cedet-cscope-min-version)
|
||||
(if (version< rev cedet-cscope-min-version)
|
||||
(if noerror
|
||||
nil
|
||||
(error "Version of CScope is %s. Need at least %s"
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
;;
|
||||
;; Basic support for calling GNU Global, and testing version numbers.
|
||||
|
||||
(declare-function inversion-check-version "inversion")
|
||||
|
||||
(defvar cedet-global-min-version "5.0"
|
||||
"Minimum version of GNU Global required.")
|
||||
|
||||
|
|
@ -143,7 +141,6 @@ If optional programmatic argument NOERROR is non-nil,
|
|||
then instead of throwing an error if Global isn't available,
|
||||
return nil."
|
||||
(interactive)
|
||||
(require 'inversion)
|
||||
(let ((b (condition-case nil
|
||||
(cedet-gnu-global-call (list "--version"))
|
||||
(error nil)))
|
||||
|
|
@ -157,7 +154,7 @@ return nil."
|
|||
(goto-char (point-min))
|
||||
(re-search-forward "(?GNU GLOBAL)? \\([0-9.]+\\)" nil t)
|
||||
(setq rev (match-string 1))
|
||||
(if (inversion-check-version rev nil cedet-global-min-version)
|
||||
(if (version< rev cedet-global-min-version)
|
||||
(if noerror
|
||||
nil
|
||||
(error "Version of GNU Global is %s. Need at least %s"
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(declare-function inversion-check-version "inversion")
|
||||
|
||||
(defvar cedet-idutils-min-version "4.0"
|
||||
"Minimum version of ID Utils required.")
|
||||
|
||||
|
|
@ -167,7 +165,6 @@ If optional programmatic argument NOERROR is non-nil,
|
|||
then instead of throwing an error if Global isn't available,
|
||||
return nil."
|
||||
(interactive)
|
||||
(require 'inversion)
|
||||
(let ((b (condition-case nil
|
||||
(cedet-idutils-fnid-call (list "--version"))
|
||||
(error nil)))
|
||||
|
|
@ -182,7 +179,7 @@ return nil."
|
|||
(if (re-search-forward "fnid - \\([0-9.]+\\)" nil t)
|
||||
(setq rev (match-string 1))
|
||||
(setq rev "0"))
|
||||
(if (inversion-check-version rev nil cedet-idutils-min-version)
|
||||
(if (version< rev cedet-idutils-min-version)
|
||||
(if noerror
|
||||
nil
|
||||
(error "Version of ID Utils is %s. Need at least %s"
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ for the specified PACKAGE.
|
|||
LOADED VERSION is the version of PACKAGE currently loaded in Emacs
|
||||
memory and (presumably) running in this Emacs instance. Value is X
|
||||
if the package has not been loaded."
|
||||
(declare (obsolete emacs-version "28.1"))
|
||||
(interactive)
|
||||
(require 'inversion)
|
||||
(with-output-to-temp-buffer "*CEDET*"
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
(setq-local eieio-ede-old-variables ov)))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'customize-project 'ede-customize-project)
|
||||
(defalias 'customize-project #'ede-customize-project)
|
||||
|
||||
;;;###autoload
|
||||
(defun ede-customize-current-target()
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
(ede-customize-target ede-object))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'customize-target 'ede-customize-current-target)
|
||||
(defalias 'customize-target #'ede-customize-current-target)
|
||||
|
||||
(defun ede-customize-target (obj)
|
||||
"Edit fields of the current target through EIEIO & Custom.
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'easymenu)
|
||||
(require 'dired)
|
||||
(require 'ede)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(declare-function inversion-check-version "inversion")
|
||||
|
||||
(defsubst ede--find-executable (exec)
|
||||
"Return an expanded file name for a program EXEC on the exec path."
|
||||
(declare (obsolete locate-file "28.1"))
|
||||
|
|
@ -60,8 +58,7 @@ If NOERROR is nil, then throw an error on failure. Return t otherwise."
|
|||
(let ((b (get-buffer-create "*EDE Make Version*"))
|
||||
(cd default-directory)
|
||||
(rev nil)
|
||||
(ans nil)
|
||||
)
|
||||
(ans nil))
|
||||
(with-current-buffer b
|
||||
;; Setup, and execute make.
|
||||
(setq default-directory cd)
|
||||
|
|
@ -70,18 +67,18 @@ If NOERROR is nil, then throw an error on failure. Return t otherwise."
|
|||
"--version")
|
||||
;; Check the buffer for the string
|
||||
(goto-char (point-min))
|
||||
(when (looking-at "GNU Make\\(?: version\\)? \\([0-9][^,]+\\),")
|
||||
(when (looking-at "GNU Make\\(?: version\\)? \\([0-9][^,[:space:]]+\\),?")
|
||||
(setq rev (match-string 1))
|
||||
(require 'inversion)
|
||||
(setq ans (not (inversion-check-version rev nil ede-make-min-version))))
|
||||
(setq ans (not (version< rev ede-make-min-version))))
|
||||
|
||||
;; Answer reporting.
|
||||
(when (and (called-interactively-p 'interactive) ans)
|
||||
(message "GNU Make version %s. Good enough for CEDET." rev))
|
||||
|
||||
(when (and (not noerror) (not ans))
|
||||
(error "EDE requires GNU Make version %s or later. Configure `ede-make-command' to fix"
|
||||
ede-make-min-version))
|
||||
(error "EDE requires GNU Make version %s or later (found %s). Configure `ede-make-command' to fix"
|
||||
ede-make-min-version
|
||||
rev))
|
||||
ans)))
|
||||
|
||||
(provide 'ede/make)
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ excluded if a released version is required.
|
|||
It is assumed that if the current version is newer than that specified,
|
||||
everything passes. Exceptions occur when known incompatibilities are
|
||||
introduced."
|
||||
(declare (obsolete emacs-version "28.1"))
|
||||
(require 'inversion)
|
||||
(inversion-test 'semantic
|
||||
(concat major "." minor
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/analyze.el --- Analyze semantic tags against local context
|
||||
;;; semantic/analyze.el --- Analyze semantic tags against local context -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2000-2005, 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ of the parent function.")
|
|||
;; Simple methods against the context classes.
|
||||
;;
|
||||
(cl-defmethod semantic-analyze-type-constraint
|
||||
((context semantic-analyze-context) &optional desired-type)
|
||||
((_context semantic-analyze-context) &optional desired-type)
|
||||
"Return a type constraint for completing :prefix in CONTEXT.
|
||||
Optional argument DESIRED-TYPE may be a non-type tag to analyze."
|
||||
(when (semantic-tag-p desired-type)
|
||||
|
|
@ -344,8 +344,8 @@ This function knows of flags:
|
|||
(setq tagtype (cons tmptype tagtype))
|
||||
(when miniscope
|
||||
(let ((rawscope
|
||||
(apply 'append
|
||||
(mapcar 'semantic-tag-type-members tagtype))))
|
||||
(apply #'append
|
||||
(mapcar #'semantic-tag-type-members tagtype))))
|
||||
(oset miniscope fullscope rawscope)))
|
||||
)
|
||||
(setq s (cdr s)))
|
||||
|
|
@ -437,6 +437,8 @@ to provide a large number of non-cached analysis for filtering symbols."
|
|||
(:override)))
|
||||
)
|
||||
|
||||
(defvar semantic--prefixtypes)
|
||||
|
||||
(defun semantic-analyze-current-symbol-default (analyzehookfcn position)
|
||||
"Call ANALYZEHOOKFCN on the analyzed symbol at POSITION."
|
||||
(let* ((semantic-analyze-error-stack nil)
|
||||
|
|
@ -453,14 +455,14 @@ to provide a large number of non-cached analysis for filtering symbols."
|
|||
(catch 'unfindable
|
||||
;; If debug on error is on, allow debugging in this fcn.
|
||||
(setq prefix (semantic-analyze-find-tag-sequence
|
||||
prefix scope 'prefixtypes 'unfindable)))
|
||||
prefix scope 'semantic--prefixtypes 'unfindable)))
|
||||
;; Debug on error is off. Capture errors and move on
|
||||
(condition-case err
|
||||
;; NOTE: This line is duplicated in
|
||||
;; semantic-analyzer-debug-global-symbol
|
||||
;; You will need to update both places.
|
||||
(setq prefix (semantic-analyze-find-tag-sequence
|
||||
prefix scope 'prefixtypes))
|
||||
prefix scope 'semantic--prefixtypes))
|
||||
(error (semantic-analyze-push-error err))))
|
||||
|
||||
;;(message "Analysis took %.2f sec" (semantic-elapsed-time LLstart nil))
|
||||
|
|
@ -531,7 +533,7 @@ Returns an object based on symbol `semantic-analyze-context'."
|
|||
(bounds (nth 2 prefixandbounds))
|
||||
;; @todo - vv too early to really know this answer! vv
|
||||
(prefixclass (semantic-ctxt-current-class-list))
|
||||
(prefixtypes nil)
|
||||
(semantic--prefixtypes nil)
|
||||
(scope (semantic-calculate-scope position))
|
||||
(function nil)
|
||||
(fntag nil)
|
||||
|
|
@ -611,13 +613,13 @@ Returns an object based on symbol `semantic-analyze-context'."
|
|||
(if debug-on-error
|
||||
(catch 'unfindable
|
||||
(setq prefix (semantic-analyze-find-tag-sequence
|
||||
prefix scope 'prefixtypes 'unfindable))
|
||||
prefix scope 'semantic--prefixtypes 'unfindable))
|
||||
;; If there's an alias, dereference it and analyze
|
||||
;; sequence again.
|
||||
(when (setq newseq
|
||||
(semantic-analyze-dereference-alias prefix))
|
||||
(setq prefix (semantic-analyze-find-tag-sequence
|
||||
newseq scope 'prefixtypes 'unfindable))))
|
||||
newseq scope 'semantic--prefixtypes 'unfindable))))
|
||||
;; Debug on error is off. Capture errors and move on
|
||||
(condition-case err
|
||||
;; NOTE: This line is duplicated in
|
||||
|
|
@ -625,11 +627,11 @@ Returns an object based on symbol `semantic-analyze-context'."
|
|||
;; You will need to update both places.
|
||||
(progn
|
||||
(setq prefix (semantic-analyze-find-tag-sequence
|
||||
prefix scope 'prefixtypes))
|
||||
prefix scope 'semantic--prefixtypes))
|
||||
(when (setq newseq
|
||||
(semantic-analyze-dereference-alias prefix))
|
||||
(setq prefix (semantic-analyze-find-tag-sequence
|
||||
newseq scope 'prefixtypes))))
|
||||
newseq scope 'semantic--prefixtypes))))
|
||||
(error (semantic-analyze-push-error err))))
|
||||
)
|
||||
|
||||
|
|
@ -650,7 +652,7 @@ Returns an object based on symbol `semantic-analyze-context'."
|
|||
:prefix prefix
|
||||
:prefixclass prefixclass
|
||||
:bounds bounds
|
||||
:prefixtypes prefixtypes
|
||||
:prefixtypes semantic--prefixtypes
|
||||
:errors semantic-analyze-error-stack)))
|
||||
|
||||
;; No function, try assignment
|
||||
|
|
@ -670,7 +672,7 @@ Returns an object based on symbol `semantic-analyze-context'."
|
|||
:bounds bounds
|
||||
:prefix prefix
|
||||
:prefixclass prefixclass
|
||||
:prefixtypes prefixtypes
|
||||
:prefixtypes semantic--prefixtypes
|
||||
:errors semantic-analyze-error-stack)))
|
||||
|
||||
;; TODO: Identify return value condition.
|
||||
|
|
@ -686,7 +688,7 @@ Returns an object based on symbol `semantic-analyze-context'."
|
|||
:bounds bounds
|
||||
:prefix prefix
|
||||
:prefixclass prefixclass
|
||||
:prefixtypes prefixtypes
|
||||
:prefixtypes semantic--prefixtypes
|
||||
:errors semantic-analyze-error-stack)))
|
||||
|
||||
(t (setq context-return nil))
|
||||
|
|
@ -750,7 +752,7 @@ Some useful functions are found in `semantic-format-tag-functions'."
|
|||
:group 'semantic
|
||||
:type semantic-format-tag-custom-list)
|
||||
|
||||
(defun semantic-analyze-princ-sequence (sequence &optional prefix buff)
|
||||
(defun semantic-analyze-princ-sequence (sequence &optional prefix _buff)
|
||||
"Send the tag SEQUENCE to standard out.
|
||||
Use PREFIX as a label.
|
||||
Use BUFF as a source of override methods."
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/analyze/complete.el --- Smart Completions
|
||||
;;; semantic/analyze/complete.el --- Smart Completions -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
"For the tag TYPE, return any constant symbols of TYPE.
|
||||
Used as options when completing.")
|
||||
|
||||
(defun semantic-analyze-type-constants-default (type)
|
||||
(defun semantic-analyze-type-constants-default (_type)
|
||||
"Do nothing with TYPE."
|
||||
nil)
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ Used as options when completing.")
|
|||
(let ((origc tags))
|
||||
;; Accept only tags that are of the datatype specified by
|
||||
;; the desired classes.
|
||||
(setq tags (apply 'nconc ;; All input lists are permutable.
|
||||
(setq tags (apply #'nconc ;; All input lists are permutable.
|
||||
(mapcar (lambda (class)
|
||||
(semantic-find-tags-by-class class origc))
|
||||
classlist)))
|
||||
|
|
@ -109,6 +109,8 @@ in a buffer."
|
|||
(when (called-interactively-p 'any)
|
||||
(error "Buffer was not parsed by Semantic."))))
|
||||
|
||||
(defvar semantic--prefixtypes)
|
||||
|
||||
(defun semantic-analyze-possible-completions-default (context &optional flags)
|
||||
"Default method for producing smart completions.
|
||||
Argument CONTEXT is an object specifying the locally derived context.
|
||||
|
|
@ -121,14 +123,14 @@ FLAGS can be any number of:
|
|||
(desired-type (semantic-analyze-type-constraint a))
|
||||
(desired-class (oref a prefixclass))
|
||||
(prefix (oref a prefix))
|
||||
(prefixtypes (oref a prefixtypes))
|
||||
(semantic--prefixtypes (oref a prefixtypes))
|
||||
(completetext nil)
|
||||
(completetexttype nil)
|
||||
(scope (oref a scope))
|
||||
(localvar (when scope (oref scope localvar)))
|
||||
(origc nil)
|
||||
(c nil)
|
||||
(any nil)
|
||||
;; (any nil)
|
||||
(do-typeconstraint (not (memq 'no-tc flags)))
|
||||
(do-longprefix (not (memq 'no-longprefix flags)))
|
||||
(do-unique (not (memq 'no-unique flags)))
|
||||
|
|
@ -138,7 +140,7 @@ FLAGS can be any number of:
|
|||
;; If we are not doing the long prefix, shorten all the key
|
||||
;; elements.
|
||||
(setq prefix (list (car (reverse prefix)))
|
||||
prefixtypes nil))
|
||||
semantic--prefixtypes nil))
|
||||
|
||||
;; Calculate what our prefix string is so that we can
|
||||
;; find all our matching text.
|
||||
|
|
@ -155,7 +157,7 @@ FLAGS can be any number of:
|
|||
;; The prefixtypes should always be at least 1 less than
|
||||
;; the prefix since the type is never looked up for the last
|
||||
;; item when calculating a sequence.
|
||||
(setq completetexttype (car (reverse prefixtypes)))
|
||||
(setq completetexttype (car (reverse semantic--prefixtypes)))
|
||||
(when (or (not completetexttype)
|
||||
(not (and (semantic-tag-p completetexttype)
|
||||
(eq (semantic-tag-class completetexttype) 'type))))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/analyze/debug.el --- Debug the analyzer
|
||||
;;; semantic/analyze/debug.el --- Debug the analyzer -*- lexical-binding: t; -*-
|
||||
|
||||
;;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -109,11 +109,11 @@ Argument COMP are possible completions here."
|
|||
(condition-case err
|
||||
(with-current-buffer origbuf
|
||||
(let* ((position (or (cdr-safe (oref ctxt bounds)) (point)))
|
||||
(prefixtypes nil) ; Used as type return
|
||||
;; (semantic--prefixtypes nil) ; Used as type return
|
||||
(scope (semantic-calculate-scope position))
|
||||
)
|
||||
(semantic-analyze-find-tag-sequence
|
||||
(list prefix "") scope 'prefixtypes)
|
||||
(list prefix "") scope) ;; 'semantic--prefixtypes
|
||||
)
|
||||
)
|
||||
(error (setq finderr err)))
|
||||
|
|
@ -149,7 +149,7 @@ path was setup incorrectly.\n")
|
|||
(semantic-analyzer-debug-add-buttons)
|
||||
))
|
||||
|
||||
(defun semantic-analyzer-debug-missing-datatype (ctxt idx comp)
|
||||
(defun semantic-analyzer-debug-missing-datatype (ctxt idx _comp)
|
||||
"Debug why we can't find a datatype entry for CTXT prefix at IDX.
|
||||
Argument COMP are possible completions here."
|
||||
(let* ((prefixitem (nth idx (oref ctxt prefix)))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/analyze/fcn.el --- Analyzer support functions.
|
||||
;;; semantic/analyze/fcn.el --- Analyzer support functions. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ Return the string representing the compound name.")
|
|||
|
||||
(defun semantic-analyze-unsplit-name-default (namelist)
|
||||
"Concatenate the names in NAMELIST with a . between."
|
||||
(mapconcat 'identity namelist "."))
|
||||
(mapconcat #'identity namelist "."))
|
||||
|
||||
;;; SELECTING
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/analyze/refs.el --- Analysis of the references between tags.
|
||||
;;; semantic/analyze/refs.el --- Analysis of the references between tags. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ Only works for tags in the global namespace."
|
|||
(let* ((classmatch (semantic-tag-class tag))
|
||||
(RES
|
||||
(semanticdb-find-tags-collector
|
||||
(lambda (table tags)
|
||||
(lambda (_table tags)
|
||||
(semantic-find-tags-by-class classmatch tags)
|
||||
;; @todo - Add parent check also.
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/bovine.el --- LL Parser/Analyzer core.
|
||||
;;; semantic/bovine.el --- LL Parser/Analyzer core -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 1999-2004, 2006-2007, 2009-2021 Free Software
|
||||
;; Foundation, Inc.
|
||||
|
|
@ -54,6 +54,7 @@ Use this to detect infinite recursion during a parse.")
|
|||
"Create a lambda expression to return a list including RETURN-VAL.
|
||||
The return list is a lambda expression to be used in a bovine table."
|
||||
`(lambda (vals start end)
|
||||
(ignore vals)
|
||||
(append ,@return-val (list start end))))
|
||||
|
||||
;;; Semantic Bovination
|
||||
|
|
@ -283,7 +284,7 @@ list of semantic tokens found."
|
|||
|
||||
;; Make it the default parser
|
||||
;;;###autoload
|
||||
(defalias 'semantic-parse-stream-default 'semantic-bovinate-stream)
|
||||
(defalias 'semantic-parse-stream-default #'semantic-bovinate-stream)
|
||||
|
||||
(provide 'semantic/bovine)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/bovine/grammar.el --- Bovine's input grammar mode
|
||||
;;; semantic/bovine/grammar.el --- Bovine's input grammar mode -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
;;
|
||||
|
|
@ -243,7 +243,8 @@ QUOTEMODE is the mode in which quoted symbols are slurred."
|
|||
(insert "\n")
|
||||
(cond
|
||||
((eq (car sexp) 'EXPAND)
|
||||
(insert ",(lambda (vals start end)")
|
||||
(insert ",(lambda (vals start end)"
|
||||
"\n(ignore vals start end)")
|
||||
;; The EXPAND macro definition is mandatory
|
||||
(bovine-grammar-expand-form
|
||||
(apply (cdr (assq 'EXPAND bovine--grammar-macros)) (cdr sexp))
|
||||
|
|
@ -520,7 +521,8 @@ Menu items are appended to the common grammar menu.")
|
|||
(goto-char (point-min))
|
||||
(delete-region (point-min) (line-end-position))
|
||||
(insert ";;; " packagename
|
||||
" --- Generated parser support file")
|
||||
" --- Generated parser support file "
|
||||
"-*- lexical-binding:t -*-")
|
||||
(delete-trailing-whitespace)
|
||||
(re-search-forward ";;; \\(.*\\) ends here")
|
||||
(replace-match packagename nil nil nil 1)))))
|
||||
|
|
|
|||
|
|
@ -154,8 +154,6 @@ If DIRECTORY doesn't exist, create a new one."
|
|||
|
||||
;;; File IO
|
||||
|
||||
(declare-function inversion-test "inversion")
|
||||
|
||||
(defun semanticdb-load-database (filename)
|
||||
"Load the database FILENAME."
|
||||
(condition-case foo
|
||||
|
|
@ -163,32 +161,19 @@ If DIRECTORY doesn't exist, create a new one."
|
|||
'semanticdb-project-database-file))
|
||||
(c (semanticdb-get-database-tables r))
|
||||
(tv (oref r semantic-tag-version))
|
||||
(fv (oref r semanticdb-version))
|
||||
)
|
||||
(fv (oref r semanticdb-version)))
|
||||
;; Restore the parent-db connection
|
||||
(while c
|
||||
(oset (car c) parent-db r)
|
||||
(setq c (cdr c)))
|
||||
(unless (and (equal semanticdb-file-version fv)
|
||||
(equal semantic-tag-version tv))
|
||||
;; Try not to load inversion unless we need it:
|
||||
(require 'inversion)
|
||||
(if (not (inversion-test 'semanticdb-file fv))
|
||||
(when (inversion-test 'semantic-tag tv)
|
||||
;; Incompatible version. Flush tables.
|
||||
(semanticdb-flush-database-tables r)
|
||||
;; Reset the version to new version.
|
||||
(oset r semantic-tag-version semantic-tag-version)
|
||||
;; Warn user
|
||||
(message "Semanticdb file is old. Starting over for %s"
|
||||
filename))
|
||||
;; Version is not ok. Flush whole system
|
||||
(message "semanticdb file is old. Starting over for %s"
|
||||
filename)
|
||||
;; This database is so old, we need to replace it.
|
||||
;; We also need to delete it from the instance tracker.
|
||||
(delete-instance r)
|
||||
(setq r nil)))
|
||||
;; Version is not ok. Flush whole system
|
||||
(message "semanticdb file is old. Starting over for %s" filename)
|
||||
;; This database is so old, we need to replace it.
|
||||
;; We also need to delete it from the instance tracker.
|
||||
(delete-instance r)
|
||||
(setq r nil))
|
||||
r)
|
||||
(error (message "Cache Error: [%s] %s, Restart"
|
||||
filename foo)
|
||||
|
|
|
|||
|
|
@ -162,10 +162,9 @@ Lays claim to all -by.el, and -wy.el files."
|
|||
"Insert variables needed by target THIS."
|
||||
(ede-proj-makefile-insert-loadpath-items
|
||||
(ede-proj-elisp-packages-to-loadpath
|
||||
(list "eieio" "semantic" "inversion" "ede")))
|
||||
(list "eieio" "semantic" "ede")))
|
||||
;; eieio for object system needed in ede
|
||||
;; semantic because it is
|
||||
;; Inversion for versioning system.
|
||||
;; ede for project regeneration
|
||||
(ede-pmake-insert-variable-shared
|
||||
(concat (ede-pmake-varname this) "_SEMANTIC_GRAMMAR_EL")
|
||||
|
|
@ -174,8 +173,7 @@ Lays claim to all -by.el, and -wy.el files."
|
|||
(with-current-buffer (find-file-noselect src)
|
||||
(concat (semantic-grammar-package) ".el")))
|
||||
(oref this source)
|
||||
" ")))
|
||||
)
|
||||
" "))))
|
||||
|
||||
(cl-defmethod ede-proj-makefile-insert-rules :after ((this semantic-ede-proj-target-grammar))
|
||||
"Insert rules needed by THIS target.
|
||||
|
|
|
|||
|
|
@ -828,8 +828,7 @@ This function is for internal use by `semantic-edits-incremental-parser'."
|
|||
|
||||
;; Make it the default changes parser
|
||||
;;;###autoload
|
||||
(defalias 'semantic-parse-changes-default
|
||||
'semantic-edits-incremental-parser)
|
||||
(defalias 'semantic-parse-changes-default #'semantic-edits-incremental-parser)
|
||||
|
||||
;;; Cache Splicing
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
;;; semantic/grammar-wy.el --- Generated parser support file
|
||||
;;; semantic/grammar-wy.el --- Generated parser support file -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2002-2004, 2009-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'semantic)
|
||||
|
||||
(require 'semantic/lex)
|
||||
(eval-when-compile (require 'semantic/bovine))
|
||||
|
||||
;;; Prologue
|
||||
;;
|
||||
(defvar semantic-grammar-lex-c-char-re)
|
||||
|
|
@ -36,16 +37,20 @@
|
|||
|
||||
;;; Declarations
|
||||
;;
|
||||
(eval-and-compile (defconst semantic-grammar-wy--expected-conflicts
|
||||
nil
|
||||
"The number of expected shift/reduce conflicts in this grammar."))
|
||||
|
||||
(defconst semantic-grammar-wy--keyword-table
|
||||
(semantic-lex-make-keyword-table
|
||||
'(("%default-prec" . DEFAULT-PREC)
|
||||
("%no-default-prec" . NO-DEFAULT-PREC)
|
||||
("%keyword" . KEYWORD)
|
||||
("%expectedconflicts" . EXPECTEDCONFLICTS)
|
||||
("%languagemode" . LANGUAGEMODE)
|
||||
("%left" . LEFT)
|
||||
("%nonassoc" . NONASSOC)
|
||||
("%package" . PACKAGE)
|
||||
("%expectedconflicts" . EXPECTEDCONFLICTS)
|
||||
("%provide" . PROVIDE)
|
||||
("%prec" . PREC)
|
||||
("%put" . PUT)
|
||||
|
|
@ -111,239 +116,239 @@
|
|||
(eval-when-compile
|
||||
(require 'semantic/wisent/comp))
|
||||
(wisent-compile-grammar
|
||||
'((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE EXPECTEDCONFLICTS LEFT NONASSOC PACKAGE PROVIDE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT)
|
||||
'((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE EXPECTEDCONFLICTS PROVIDE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT)
|
||||
nil
|
||||
(grammar
|
||||
((prologue))
|
||||
((epilogue))
|
||||
((declaration))
|
||||
((nonterminal))
|
||||
((PERCENT_PERCENT)))
|
||||
((prologue))
|
||||
((epilogue))
|
||||
((declaration))
|
||||
((nonterminal))
|
||||
((PERCENT_PERCENT)))
|
||||
(prologue
|
||||
((PROLOGUE)
|
||||
(wisent-raw-tag
|
||||
((PROLOGUE)
|
||||
(wisent-raw-tag
|
||||
(semantic-tag-new-code "prologue" nil))))
|
||||
(epilogue
|
||||
((EPILOGUE)
|
||||
(wisent-raw-tag
|
||||
((EPILOGUE)
|
||||
(wisent-raw-tag
|
||||
(semantic-tag-new-code "epilogue" nil))))
|
||||
(declaration
|
||||
((decl)
|
||||
(eval $1)))
|
||||
((decl)
|
||||
(eval $1)))
|
||||
(decl
|
||||
((default_prec_decl))
|
||||
((no_default_prec_decl))
|
||||
((languagemode_decl))
|
||||
((expectedconflicts_decl))
|
||||
((package_decl))
|
||||
((provide_decl))
|
||||
((precedence_decl))
|
||||
((put_decl))
|
||||
((quotemode_decl))
|
||||
((scopestart_decl))
|
||||
((start_decl))
|
||||
((keyword_decl))
|
||||
((token_decl))
|
||||
((type_decl))
|
||||
((use_macros_decl)))
|
||||
((default_prec_decl))
|
||||
((no_default_prec_decl))
|
||||
((languagemode_decl))
|
||||
((package_decl))
|
||||
((expectedconflicts_decl))
|
||||
((provide_decl))
|
||||
((precedence_decl))
|
||||
((put_decl))
|
||||
((quotemode_decl))
|
||||
((scopestart_decl))
|
||||
((start_decl))
|
||||
((keyword_decl))
|
||||
((token_decl))
|
||||
((type_decl))
|
||||
((use_macros_decl)))
|
||||
(default_prec_decl
|
||||
((DEFAULT-PREC)
|
||||
((DEFAULT-PREC)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag "default-prec" 'assoc :value
|
||||
'("t")))))
|
||||
(no_default_prec_decl
|
||||
((NO-DEFAULT-PREC)
|
||||
`(wisent-raw-tag
|
||||
((NO-DEFAULT-PREC)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag "default-prec" 'assoc :value
|
||||
'("nil")))))
|
||||
'("nil")))))
|
||||
(languagemode_decl
|
||||
((LANGUAGEMODE symbols)
|
||||
`(wisent-raw-tag
|
||||
((LANGUAGEMODE symbols)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $2)
|
||||
'languagemode :rest ',(cdr $2)))))
|
||||
(expectedconflicts_decl
|
||||
((EXPECTEDCONFLICTS symbols)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $2)
|
||||
'expectedconflicts :rest ',(cdr $2)))))
|
||||
'languagemode :rest ',(cdr $2)))))
|
||||
(package_decl
|
||||
((PACKAGE SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
((PACKAGE SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag-new-package ',$2 nil))))
|
||||
(expectedconflicts_decl
|
||||
((EXPECTEDCONFLICTS symbols)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $2)
|
||||
'expectedconflicts :rest ',(cdr $2)))))
|
||||
(provide_decl
|
||||
((PROVIDE SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
((PROVIDE SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'provide))))
|
||||
(precedence_decl
|
||||
((associativity token_type_opt items)
|
||||
`(wisent-raw-tag
|
||||
((associativity token_type_opt items)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$1 'assoc :type ',$2 :value ',$3))))
|
||||
(associativity
|
||||
((LEFT)
|
||||
(progn "left"))
|
||||
((RIGHT)
|
||||
(progn "right"))
|
||||
((NONASSOC)
|
||||
(progn "nonassoc")))
|
||||
((LEFT)
|
||||
(progn "left"))
|
||||
((RIGHT)
|
||||
(progn "right"))
|
||||
((NONASSOC)
|
||||
(progn "nonassoc")))
|
||||
(put_decl
|
||||
((PUT put_name put_value)
|
||||
`(wisent-raw-tag
|
||||
((PUT put_name put_value)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'put :value ',(list $3))))
|
||||
((PUT put_name put_value_list)
|
||||
`(wisent-raw-tag
|
||||
((PUT put_name put_value_list)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'put :value ',$3)))
|
||||
((PUT put_name_list put_value)
|
||||
`(wisent-raw-tag
|
||||
((PUT put_name_list put_value)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $2)
|
||||
'put :rest ',(cdr $2)
|
||||
:value ',(list $3))))
|
||||
((PUT put_name_list put_value_list)
|
||||
`(wisent-raw-tag
|
||||
'put :rest ',(cdr $2)
|
||||
:value ',(list $3))))
|
||||
((PUT put_name_list put_value_list)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $2)
|
||||
'put :rest ',(cdr $2)
|
||||
:value ',$3))))
|
||||
'put :rest ',(cdr $2)
|
||||
:value ',$3))))
|
||||
(put_name_list
|
||||
((BRACE_BLOCK)
|
||||
(mapcar 'semantic-tag-name
|
||||
(semantic-parse-region
|
||||
((BRACE_BLOCK)
|
||||
(mapcar 'semantic-tag-name
|
||||
(semantic-parse-region
|
||||
(car $region1)
|
||||
(cdr $region1)
|
||||
'put_names 1))))
|
||||
(put_names
|
||||
((LBRACE)
|
||||
nil)
|
||||
((RBRACE)
|
||||
nil)
|
||||
((put_name)
|
||||
(wisent-raw-tag
|
||||
((LBRACE)
|
||||
nil)
|
||||
((RBRACE)
|
||||
nil)
|
||||
((put_name)
|
||||
(wisent-raw-tag
|
||||
(semantic-tag $1 'put-name))))
|
||||
(put_name
|
||||
((SYMBOL))
|
||||
((token_type)))
|
||||
((SYMBOL))
|
||||
((token_type)))
|
||||
(put_value_list
|
||||
((BRACE_BLOCK)
|
||||
(mapcar 'semantic-tag-code-detail
|
||||
(semantic-parse-region
|
||||
((BRACE_BLOCK)
|
||||
(mapcar 'semantic-tag-code-detail
|
||||
(semantic-parse-region
|
||||
(car $region1)
|
||||
(cdr $region1)
|
||||
'put_values 1))))
|
||||
(put_values
|
||||
((LBRACE)
|
||||
nil)
|
||||
((RBRACE)
|
||||
nil)
|
||||
((put_value)
|
||||
(wisent-raw-tag
|
||||
((LBRACE)
|
||||
nil)
|
||||
((RBRACE)
|
||||
nil)
|
||||
((put_value)
|
||||
(wisent-raw-tag
|
||||
(semantic-tag-new-code "put-value" $1))))
|
||||
(put_value
|
||||
((SYMBOL any_value)
|
||||
(cons $1 $2)))
|
||||
((SYMBOL any_value)
|
||||
(cons $1 $2)))
|
||||
(scopestart_decl
|
||||
((SCOPESTART SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
((SCOPESTART SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'scopestart))))
|
||||
(quotemode_decl
|
||||
((QUOTEMODE SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
((QUOTEMODE SYMBOL)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'quotemode))))
|
||||
(start_decl
|
||||
((START symbols)
|
||||
`(wisent-raw-tag
|
||||
((START symbols)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $2)
|
||||
'start :rest ',(cdr $2)))))
|
||||
'start :rest ',(cdr $2)))))
|
||||
(keyword_decl
|
||||
((KEYWORD SYMBOL string_value)
|
||||
`(wisent-raw-tag
|
||||
((KEYWORD SYMBOL string_value)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'keyword :value ',$3))))
|
||||
(token_decl
|
||||
((TOKEN token_type_opt SYMBOL string_value)
|
||||
`(wisent-raw-tag
|
||||
((TOKEN token_type_opt SYMBOL string_value)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$3 ',(if $2 'token 'keyword)
|
||||
:type ',$2 :value ',$4)))
|
||||
((TOKEN token_type_opt symbols)
|
||||
`(wisent-raw-tag
|
||||
:type ',$2 :value ',$4)))
|
||||
((TOKEN token_type_opt symbols)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',(car $3)
|
||||
'token :type ',$2 :rest ',(cdr $3)))))
|
||||
'token :type ',$2 :rest ',(cdr $3)))))
|
||||
(token_type_opt
|
||||
(nil)
|
||||
((token_type)))
|
||||
(nil)
|
||||
((token_type)))
|
||||
(token_type
|
||||
((LT SYMBOL GT)
|
||||
(progn $2)))
|
||||
((LT SYMBOL GT)
|
||||
(progn $2)))
|
||||
(type_decl
|
||||
((TYPE token_type plist_opt)
|
||||
`(wisent-raw-tag
|
||||
((TYPE token_type plist_opt)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag ',$2 'type :value ',$3))))
|
||||
(plist_opt
|
||||
(nil)
|
||||
((plist)))
|
||||
(nil)
|
||||
((plist)))
|
||||
(plist
|
||||
((plist put_value)
|
||||
(append
|
||||
((plist put_value)
|
||||
(append
|
||||
(list $2)
|
||||
$1))
|
||||
((put_value)
|
||||
(list $1)))
|
||||
((put_value)
|
||||
(list $1)))
|
||||
(use_name_list
|
||||
((BRACE_BLOCK)
|
||||
(mapcar 'semantic-tag-name
|
||||
(semantic-parse-region
|
||||
((BRACE_BLOCK)
|
||||
(mapcar 'semantic-tag-name
|
||||
(semantic-parse-region
|
||||
(car $region1)
|
||||
(cdr $region1)
|
||||
'use_names 1))))
|
||||
(use_names
|
||||
((LBRACE)
|
||||
nil)
|
||||
((RBRACE)
|
||||
nil)
|
||||
((SYMBOL)
|
||||
(wisent-raw-tag
|
||||
((LBRACE)
|
||||
nil)
|
||||
((RBRACE)
|
||||
nil)
|
||||
((SYMBOL)
|
||||
(wisent-raw-tag
|
||||
(semantic-tag $1 'use-name))))
|
||||
(use_macros_decl
|
||||
((USE-MACROS SYMBOL use_name_list)
|
||||
`(wisent-raw-tag
|
||||
((USE-MACROS SYMBOL use_name_list)
|
||||
`(wisent-raw-tag
|
||||
(semantic-tag "macro" 'macro :type ',$2 :value ',$3))))
|
||||
(string_value
|
||||
((STRING)
|
||||
(read $1)))
|
||||
((STRING)
|
||||
(read $1)))
|
||||
(any_value
|
||||
((SYMBOL))
|
||||
((STRING))
|
||||
((PAREN_BLOCK))
|
||||
((PREFIXED_LIST))
|
||||
((SEXP)))
|
||||
((SYMBOL))
|
||||
((STRING))
|
||||
((PAREN_BLOCK))
|
||||
((PREFIXED_LIST))
|
||||
((SEXP)))
|
||||
(symbols
|
||||
((lifo_symbols)
|
||||
(nreverse $1)))
|
||||
((lifo_symbols)
|
||||
(nreverse $1)))
|
||||
(lifo_symbols
|
||||
((lifo_symbols SYMBOL)
|
||||
(cons $2 $1))
|
||||
((SYMBOL)
|
||||
(list $1)))
|
||||
((lifo_symbols SYMBOL)
|
||||
(cons $2 $1))
|
||||
((SYMBOL)
|
||||
(list $1)))
|
||||
(nonterminal
|
||||
((SYMBOL
|
||||
((SYMBOL
|
||||
(setq semantic-grammar-wy--nterm $1 semantic-grammar-wy--rindx 0)
|
||||
COLON rules SEMI)
|
||||
(wisent-raw-tag
|
||||
(wisent-raw-tag
|
||||
(semantic-tag $1 'nonterminal :children $4))))
|
||||
(rules
|
||||
((lifo_rules)
|
||||
(apply 'nconc
|
||||
(nreverse $1))))
|
||||
((lifo_rules)
|
||||
(apply 'nconc
|
||||
(nreverse $1))))
|
||||
(lifo_rules
|
||||
((lifo_rules OR rule)
|
||||
(cons $3 $1))
|
||||
((rule)
|
||||
(list $1)))
|
||||
((lifo_rules OR rule)
|
||||
(cons $3 $1))
|
||||
((rule)
|
||||
(list $1)))
|
||||
(rule
|
||||
((rhs)
|
||||
(let*
|
||||
((rhs)
|
||||
(let*
|
||||
((nterm semantic-grammar-wy--nterm)
|
||||
(rindx semantic-grammar-wy--rindx)
|
||||
(rhs $1)
|
||||
comps prec action elt)
|
||||
(setq semantic-grammar-wy--rindx
|
||||
(1+ semantic-grammar-wy--rindx))
|
||||
(1+ semantic-grammar-wy--rindx))
|
||||
(while rhs
|
||||
(setq elt
|
||||
(car rhs)
|
||||
|
|
@ -359,10 +364,10 @@
|
|||
(if
|
||||
(or action comps)
|
||||
(setq comps
|
||||
(cons elt comps)
|
||||
semantic-grammar-wy--rindx
|
||||
(1+ semantic-grammar-wy--rindx))
|
||||
(setq action
|
||||
(cons elt comps)
|
||||
semantic-grammar-wy--rindx
|
||||
(1+ semantic-grammar-wy--rindx))
|
||||
(setq action
|
||||
(car elt))))
|
||||
(t
|
||||
(setq comps
|
||||
|
|
@ -375,46 +380,46 @@
|
|||
(if comps "group" "empty")
|
||||
:value comps :prec prec :expr action))))))
|
||||
(rhs
|
||||
(nil)
|
||||
((rhs item)
|
||||
(cons $2 $1))
|
||||
((rhs action)
|
||||
(cons
|
||||
(nil)
|
||||
((rhs item)
|
||||
(cons $2 $1))
|
||||
((rhs action)
|
||||
(cons
|
||||
(list $2)
|
||||
$1))
|
||||
((rhs PREC item)
|
||||
(cons
|
||||
((rhs PREC item)
|
||||
(cons
|
||||
(vector $3)
|
||||
$1)))
|
||||
(action
|
||||
((PAREN_BLOCK))
|
||||
((PREFIXED_LIST))
|
||||
((BRACE_BLOCK)
|
||||
(format "(progn\n%s)"
|
||||
(let
|
||||
((PAREN_BLOCK))
|
||||
((PREFIXED_LIST))
|
||||
((BRACE_BLOCK)
|
||||
(format "(progn\n%s)"
|
||||
(let
|
||||
((s $1))
|
||||
(if
|
||||
(string-match "^{[\r\n\t ]*" s)
|
||||
(string-match "^{[
\n ]*" s)
|
||||
(setq s
|
||||
(substring s
|
||||
(match-end 0))))
|
||||
(match-end 0))))
|
||||
(if
|
||||
(string-match "[\r\n\t ]*}$" s)
|
||||
(string-match "[
\n ]*}$" s)
|
||||
(setq s
|
||||
(substring s 0
|
||||
(match-beginning 0))))
|
||||
(match-beginning 0))))
|
||||
s))))
|
||||
(items
|
||||
((lifo_items)
|
||||
(nreverse $1)))
|
||||
((lifo_items)
|
||||
(nreverse $1)))
|
||||
(lifo_items
|
||||
((lifo_items item)
|
||||
(cons $2 $1))
|
||||
((item)
|
||||
(list $1)))
|
||||
((lifo_items item)
|
||||
(cons $2 $1))
|
||||
((item)
|
||||
(list $1)))
|
||||
(item
|
||||
((SYMBOL))
|
||||
((CHARACTER))))
|
||||
((SYMBOL))
|
||||
((CHARACTER))))
|
||||
'(grammar prologue epilogue declaration nonterminal rule put_names put_values use_names)))
|
||||
"Parser table.")
|
||||
|
||||
|
|
@ -423,17 +428,38 @@
|
|||
(semantic-install-function-overrides
|
||||
'((semantic-parse-stream . wisent-parse-stream)))
|
||||
(setq semantic-parser-name "LALR"
|
||||
semantic--parse-table semantic-grammar-wy--parse-table
|
||||
semantic-debug-parser-source "grammar.wy"
|
||||
semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table
|
||||
semantic-lex-types-obarray semantic-grammar-wy--token-table)
|
||||
semantic--parse-table semantic-grammar-wy--parse-table
|
||||
semantic-debug-parser-source "grammar.wy"
|
||||
semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table
|
||||
semantic-lex-types-obarray semantic-grammar-wy--token-table)
|
||||
;; Collect unmatched syntax lexical tokens
|
||||
(add-hook 'wisent-discarding-token-functions
|
||||
'wisent-collect-unmatched-syntax nil t))
|
||||
'wisent-collect-unmatched-syntax nil t))
|
||||
|
||||
|
||||
;;; Analyzers
|
||||
;;
|
||||
(define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer
|
||||
"regexp analyzer for <symbol> tokens."
|
||||
":?\\(\\sw\\|\\s_\\)+"
|
||||
'((PERCENT_PERCENT . "\\`%%\\'"))
|
||||
'SYMBOL)
|
||||
|
||||
(define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer
|
||||
"keyword analyzer for <keyword> tokens."
|
||||
"\\(\\sw\\|\\s_\\)+")
|
||||
|
||||
(define-lex-regex-type-analyzer semantic-grammar-wy--<char>-regexp-analyzer
|
||||
"regexp analyzer for <char> tokens."
|
||||
semantic-grammar-lex-c-char-re
|
||||
nil
|
||||
'CHARACTER)
|
||||
|
||||
(define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
|
||||
"sexp analyzer for <qlist> tokens."
|
||||
"\\s'\\s-*("
|
||||
'PREFIXED_LIST)
|
||||
|
||||
(define-lex-block-type-analyzer semantic-grammar-wy--<block>-block-analyzer
|
||||
"block analyzer for <block> tokens."
|
||||
"\\s(\\|\\s)"
|
||||
|
|
@ -443,28 +469,6 @@
|
|||
("}" RBRACE))
|
||||
)
|
||||
|
||||
(define-lex-regex-type-analyzer semantic-grammar-wy--<char>-regexp-analyzer
|
||||
"regexp analyzer for <char> tokens."
|
||||
semantic-grammar-lex-c-char-re
|
||||
nil
|
||||
'CHARACTER)
|
||||
|
||||
(define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer
|
||||
"regexp analyzer for <symbol> tokens."
|
||||
":?\\(\\sw\\|\\s_\\)+"
|
||||
'((PERCENT_PERCENT . "\\`%%\\'"))
|
||||
'SYMBOL)
|
||||
|
||||
(define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
|
||||
"sexp analyzer for <qlist> tokens."
|
||||
"\\s'\\s-*("
|
||||
'PREFIXED_LIST)
|
||||
|
||||
(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
|
||||
"sexp analyzer for <string> tokens."
|
||||
"\\s\""
|
||||
'STRING)
|
||||
|
||||
(define-lex-string-type-analyzer semantic-grammar-wy--<punctuation>-string-analyzer
|
||||
"string analyzer for <punctuation> tokens."
|
||||
"\\(\\s.\\|\\s$\\|\\s'\\)+"
|
||||
|
|
@ -475,9 +479,10 @@
|
|||
(COLON . ":"))
|
||||
'punctuation)
|
||||
|
||||
(define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer
|
||||
"keyword analyzer for <keyword> tokens."
|
||||
"\\(\\sw\\|\\s_\\)+")
|
||||
(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
|
||||
"sexp analyzer for <string> tokens."
|
||||
"\\s\""
|
||||
'STRING)
|
||||
|
||||
(define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer
|
||||
"sexp analyzer for <sexp> tokens."
|
||||
|
|
@ -493,4 +498,9 @@
|
|||
|
||||
(provide 'semantic/grammar-wy)
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-update-autoloads: t
|
||||
;; End:
|
||||
|
||||
;;; semantic/grammar-wy.el ends here
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@
|
|||
;; For the semantic-find-tags-by-name macro.
|
||||
(eval-when-compile (require 'semantic/find))
|
||||
|
||||
(defvar eldoc-last-message)
|
||||
(declare-function eldoc-message "eldoc")
|
||||
(declare-function semantic-analyze-unsplit-name "semantic/analyze/fcn")
|
||||
(declare-function semantic-complete-analyze-inline-idle "semantic/complete")
|
||||
(declare-function semanticdb-deep-find-tags-by-name "semantic/db-find")
|
||||
|
|
@ -730,8 +728,8 @@ specific to a major mode. For example, in jde mode:
|
|||
:group 'semantic
|
||||
:type 'hook)
|
||||
|
||||
(defun semantic-idle-summary-idle-function ()
|
||||
"Display a tag summary of the lexical token under the cursor.
|
||||
(defun semantic--eldoc-info (_callback &rest _)
|
||||
"Return the eldoc info for the current symbol.
|
||||
Call `semantic-idle-summary-current-symbol-info' for getting the
|
||||
current tag to display information."
|
||||
(or (eq major-mode 'emacs-lisp-mode)
|
||||
|
|
@ -741,21 +739,7 @@ current tag to display information."
|
|||
((semantic-tag-p found)
|
||||
(funcall semantic-idle-summary-function
|
||||
found nil t)))))
|
||||
;; Show the message with eldoc functions
|
||||
(unless (and str (boundp 'eldoc-echo-area-use-multiline-p)
|
||||
eldoc-echo-area-use-multiline-p)
|
||||
(let ((w (1- (window-width (minibuffer-window)))))
|
||||
(if (> (length str) w)
|
||||
(setq str (substring str 0 w)))))
|
||||
;; I borrowed some bits from eldoc to shorten the
|
||||
;; message.
|
||||
(when semantic-idle-truncate-long-summaries
|
||||
(let ((ea-width (1- (window-width (minibuffer-window))))
|
||||
(strlen (length str)))
|
||||
(when (> strlen ea-width)
|
||||
(setq str (substring str 0 ea-width)))))
|
||||
;; Display it
|
||||
(eldoc-message str))))
|
||||
str)))
|
||||
|
||||
(define-minor-mode semantic-idle-summary-mode
|
||||
"Toggle Semantic Idle Summary mode.
|
||||
|
|
@ -764,30 +748,16 @@ When this minor mode is enabled, the echo area displays a summary
|
|||
of the lexical token at point whenever Emacs is idle."
|
||||
:group 'semantic
|
||||
:group 'semantic-modes
|
||||
(if semantic-idle-summary-mode
|
||||
;; Enable the mode
|
||||
(progn
|
||||
(unless (and (featurep 'semantic) (semantic-active-p))
|
||||
;; Disable minor mode if semantic stuff not available
|
||||
(setq semantic-idle-summary-mode nil)
|
||||
(error "Buffer %s was not set up for parsing"
|
||||
(buffer-name)))
|
||||
(require 'eldoc)
|
||||
(semantic-idle-scheduler-add 'semantic-idle-summary-idle-function)
|
||||
(add-hook 'pre-command-hook 'semantic-idle-summary-refresh-echo-area t))
|
||||
;; Disable the mode
|
||||
(semantic-idle-scheduler-remove 'semantic-idle-summary-idle-function)
|
||||
(remove-hook 'pre-command-hook 'semantic-idle-summary-refresh-echo-area t)))
|
||||
|
||||
(defun semantic-idle-summary-refresh-echo-area ()
|
||||
(and semantic-idle-summary-mode
|
||||
eldoc-last-message
|
||||
(if (and (not executing-kbd-macro)
|
||||
(not (and (boundp 'edebug-active) edebug-active))
|
||||
(not cursor-in-echo-area)
|
||||
(not (eq (selected-window) (minibuffer-window))))
|
||||
(eldoc-message eldoc-last-message)
|
||||
(setq eldoc-last-message nil))))
|
||||
(remove-hook 'eldoc-documentation-functions #'semantic--eldoc-info t)
|
||||
(when semantic-idle-summary-mode
|
||||
;; Enable the mode
|
||||
(unless (and (featurep 'semantic) (semantic-active-p))
|
||||
;; Disable minor mode if semantic stuff not available
|
||||
(setq semantic-idle-summary-mode nil)
|
||||
(error "Buffer %s was not set up for parsing"
|
||||
(buffer-name)))
|
||||
(add-hook 'eldoc-documentation-functions #'semantic--eldoc-info nil t)
|
||||
(eldoc-mode 1)))
|
||||
|
||||
(semantic-add-minor-mode 'semantic-idle-summary-mode "")
|
||||
|
||||
|
|
@ -1092,7 +1062,7 @@ be called."
|
|||
;; mouse-3 pops up a context menu
|
||||
(define-key map
|
||||
[ header-line mouse-3 ]
|
||||
'semantic-idle-breadcrumbs--popup-menu)
|
||||
#'semantic-idle-breadcrumbs--popup-menu)
|
||||
map)
|
||||
"Keymap for semantic idle breadcrumbs minor mode.")
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,28 @@ See also the function `semantic-ctxt-current-mode'."
|
|||
(require 'semantic/ctxt)
|
||||
(semantic-ctxt-current-mode)))))
|
||||
|
||||
;; Is this function still necessary?
|
||||
(defun semantic-tag-make-plist (args)
|
||||
"Create a property list with ARGS.
|
||||
Args is a property list of the form (KEY1 VALUE1 ... KEYN VALUEN).
|
||||
Where KEY is a symbol, and VALUE is the value for that symbol.
|
||||
The return value will be a new property list, with these KEY/VALUE
|
||||
pairs eliminated:
|
||||
|
||||
- KEY associated to nil VALUE.
|
||||
- KEY associated to an empty string VALUE.
|
||||
- KEY associated to a zero VALUE."
|
||||
(let (plist key val)
|
||||
(while args
|
||||
(setq key (car args)
|
||||
val (nth 1 args)
|
||||
args (nthcdr 2 args))
|
||||
(or (member val '("" nil))
|
||||
(and (numberp val) (zerop val))
|
||||
(setq plist (cons key (cons val plist)))))
|
||||
;; It is not useful to reverse the new plist.
|
||||
plist))
|
||||
|
||||
(defsubst semantic--tag-attributes-cdr (tag)
|
||||
"Return the cons cell whose car is the ATTRIBUTES part of TAG.
|
||||
That function is for internal use only."
|
||||
|
|
@ -441,28 +463,6 @@ class to store those methods."
|
|||
;;; Tag creation
|
||||
;;
|
||||
|
||||
;; Is this function still necessary?
|
||||
(defun semantic-tag-make-plist (args)
|
||||
"Create a property list with ARGS.
|
||||
Args is a property list of the form (KEY1 VALUE1 ... KEYN VALUEN).
|
||||
Where KEY is a symbol, and VALUE is the value for that symbol.
|
||||
The return value will be a new property list, with these KEY/VALUE
|
||||
pairs eliminated:
|
||||
|
||||
- KEY associated to nil VALUE.
|
||||
- KEY associated to an empty string VALUE.
|
||||
- KEY associated to a zero VALUE."
|
||||
(let (plist key val)
|
||||
(while args
|
||||
(setq key (car args)
|
||||
val (nth 1 args)
|
||||
args (nthcdr 2 args))
|
||||
(or (member val '("" nil))
|
||||
(and (numberp val) (zerop val))
|
||||
(setq plist (cons key (cons val plist)))))
|
||||
;; It is not useful to reverse the new plist.
|
||||
plist))
|
||||
|
||||
(defsubst semantic-tag (name class &rest attributes)
|
||||
"Create a generic semantic tag.
|
||||
NAME is a string representing the name of this tag.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; semantic/wisent/grammar.el --- Wisent's input grammar mode
|
||||
;;; semantic/wisent/grammar.el --- Wisent's input grammar mode -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
;;
|
||||
|
|
@ -228,7 +228,7 @@ Keep order of declaration in the WY file without duplicates."
|
|||
Return the expanded expression."
|
||||
(if (or (atom expr) (semantic-grammar-quote-p (car expr)))
|
||||
expr ;; Just return atom or quoted expression.
|
||||
(let* ((expr (mapcar 'wisent-grammar-expand-macros expr))
|
||||
(let* ((expr (mapcar #'wisent-grammar-expand-macros expr))
|
||||
(macro (assq (car expr) wisent--grammar-macros)))
|
||||
(if macro ;; Expand Semantic built-in.
|
||||
(apply (cdr macro) (cdr expr))
|
||||
|
|
@ -514,7 +514,8 @@ Menu items are appended to the common grammar menu.")
|
|||
(goto-char (point-min))
|
||||
(delete-region (point-min) (line-end-position))
|
||||
(insert ";;; " packagename
|
||||
" --- Generated parser support file")
|
||||
" --- Generated parser support file "
|
||||
"-*- lexical-binding:t -*-")
|
||||
(re-search-forward ";;; \\(.*\\) ends here")
|
||||
(replace-match packagename nil nil nil 1)
|
||||
(delete-trailing-whitespace))))))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/args.el --- Provide some simple template arguments
|
||||
;;; srecode/args.el --- Provide some simple template arguments -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/compile --- Compilation of srecode template files.
|
||||
;;; srecode/compile --- Compilation of srecode template files. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -499,7 +499,7 @@ PROPS are additional properties that might need to be passed
|
|||
to the inserter constructor."
|
||||
;;(message "Compile: %s %S" name props)
|
||||
(if (not key)
|
||||
(apply 'srecode-template-inserter-variable name props)
|
||||
(apply #'make-instance 'srecode-template-inserter-variable name props)
|
||||
(let ((classes (eieio-class-children 'srecode-template-inserter))
|
||||
(new nil))
|
||||
;; Loop over the various subclasses and
|
||||
|
|
@ -510,7 +510,7 @@ to the inserter constructor."
|
|||
(when (and (not (class-abstract-p (car classes)))
|
||||
(equal (oref-default (car classes) key) key))
|
||||
;; Create the new class, and apply state.
|
||||
(setq new (apply (car classes) name props))
|
||||
(setq new (apply #'make-instance (car classes) name props))
|
||||
(srecode-inserter-apply-state new STATE)
|
||||
)
|
||||
(setq classes (cdr classes)))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder
|
||||
;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -44,7 +44,6 @@
|
|||
A dictionary entry of the named PREFIX_NAMESPACE with the value
|
||||
NAMESPACE:: is created for each namespace unless the current
|
||||
buffer contains a using NAMESPACE; statement."
|
||||
:group 'srecode-cpp
|
||||
:type '(repeat string))
|
||||
|
||||
;;; :c ARGUMENT HANDLING
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/ctxt.el --- Derive a context from the source buffer.
|
||||
;;; srecode/ctxt.el --- Derive a context from the source buffer. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/dictionary.el --- Dictionary code for the semantic recoder.
|
||||
;;; srecode/dictionary.el --- Dictionary code for the semantic recoder. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -443,8 +443,8 @@ The root dictionary is usually for a current or active insertion."
|
|||
;; for use in converting the compound value into something insertable.
|
||||
|
||||
(cl-defmethod srecode-compound-toString ((cp srecode-dictionary-compound-value)
|
||||
function
|
||||
dictionary)
|
||||
_function
|
||||
_dictionary)
|
||||
"Convert the compound dictionary value CP to a string.
|
||||
If FUNCTION is non-nil, then FUNCTION is somehow applied to an aspect
|
||||
of the compound value. The FUNCTION could be a fraction
|
||||
|
|
@ -457,14 +457,15 @@ standard out is a buffer, and using `insert'."
|
|||
(eieio-object-name cp))
|
||||
|
||||
(cl-defmethod srecode-dump ((cp srecode-dictionary-compound-value)
|
||||
&optional indent)
|
||||
&optional _indent)
|
||||
"Display information about this compound value."
|
||||
(princ (eieio-object-name cp))
|
||||
)
|
||||
|
||||
(cl-defmethod srecode-compound-toString ((cp srecode-dictionary-compound-variable)
|
||||
function
|
||||
dictionary)
|
||||
(cl-defmethod srecode-compound-toString
|
||||
((cp srecode-dictionary-compound-variable)
|
||||
_function
|
||||
dictionary)
|
||||
"Convert the compound dictionary variable value CP into a string.
|
||||
FUNCTION and DICTIONARY are as for the baseclass."
|
||||
(require 'srecode/insert)
|
||||
|
|
@ -606,9 +607,9 @@ STATE is the current compiler state."
|
|||
(require 'srecode/find)
|
||||
(let* ((modesym major-mode)
|
||||
(start (current-time))
|
||||
(junk (or (progn (srecode-load-tables-for-mode modesym)
|
||||
(srecode-get-mode-table modesym))
|
||||
(error "No table found for mode %S" modesym)))
|
||||
(_ (or (progn (srecode-load-tables-for-mode modesym)
|
||||
(srecode-get-mode-table modesym))
|
||||
(error "No table found for mode %S" modesym)))
|
||||
(dict (srecode-create-dictionary (current-buffer)))
|
||||
)
|
||||
(message "Creating a dictionary took %.2f seconds."
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/document.el --- Documentation (comment) generation
|
||||
;;; srecode/document.el --- Documentation (comment) generation -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -88,7 +88,6 @@ versions of names. This is an alist with each element of the form:
|
|||
(MATCH . RESULT)
|
||||
MATCH is a regexp to match in the type field.
|
||||
RESULT is a string."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -144,7 +143,6 @@ A string may end in a space, in which case, last-alist is searched to
|
|||
see how best to describe what can be returned.
|
||||
Doesn't always work correctly, but that is just because English
|
||||
doesn't always work correctly."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -175,7 +173,6 @@ versions of names. This is an alist with each element of the form:
|
|||
(MATCH . RESULT)
|
||||
MATCH is a regexp to match in the type field.
|
||||
RESULT is a string."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -192,7 +189,6 @@ This is an alist with each element of the form:
|
|||
(MATCH . RESULT)
|
||||
MATCH is a regexp to match in the type field.
|
||||
RESULT is a string."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -213,7 +209,6 @@ This is an alist with each element of the form:
|
|||
MATCH is a regexp to match in the type field.
|
||||
RESULT is a string, which can contain %s, which is replaced with
|
||||
`match-string' 1."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -233,7 +228,6 @@ MATCH is a regexp to match in the type field.
|
|||
RESULT is a string of text to use to describe MATCH.
|
||||
When one is encountered, document-insert-parameters will automatically
|
||||
place this comment after the parameter name."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -258,7 +252,6 @@ This is an alist with each element of the form:
|
|||
(MATCH . RESULT)
|
||||
MATCH is a regexp to match in the type field.
|
||||
RESULT is a string."
|
||||
:group 'document
|
||||
:type '(repeat (cons (regexp :tag "Regexp")
|
||||
(string :tag "Doc Text"))))
|
||||
|
||||
|
|
@ -716,7 +709,7 @@ allocating something based on its type."
|
|||
(setq al (cdr al)))))
|
||||
news))
|
||||
|
||||
(defun srecode-document-parameter-comment (param &optional commentlist)
|
||||
(defun srecode-document-parameter-comment (param &optional _commentlist)
|
||||
"Convert tag or string PARAM into a name,comment pair.
|
||||
Optional COMMENTLIST is list of previously existing comments to
|
||||
use instead in alist form. If the name doesn't appear in the list of
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/el.el --- Emacs Lisp specific arguments
|
||||
;;; srecode/el.el --- Emacs Lisp specific arguments -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/expandproto.el --- Expanding prototypes.
|
||||
;;; srecode/expandproto.el --- Expanding prototypes. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/extract.el --- Extract content from previously inserted macro.
|
||||
;;; srecode/extract.el --- Extract content from previously inserted macro. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -139,24 +139,24 @@ Uses STATE to maintain the current extraction state."
|
|||
|
||||
;;; Inserter Base Extractors
|
||||
;;
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((ins srecode-template-inserter))
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((_ins srecode-template-inserter))
|
||||
"Return non-nil if this inserter can extract values."
|
||||
nil)
|
||||
|
||||
(cl-defmethod srecode-inserter-extract ((ins srecode-template-inserter)
|
||||
start end dict state)
|
||||
(cl-defmethod srecode-inserter-extract ((_ins srecode-template-inserter)
|
||||
_start _end _dict _state)
|
||||
"Extract text from START/END and store in DICT.
|
||||
Return nil as this inserter will extract nothing."
|
||||
nil)
|
||||
|
||||
;;; Variable extractor is simple and can extract later.
|
||||
;;
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((ins srecode-template-inserter-variable))
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((_ins srecode-template-inserter-variable))
|
||||
"Return non-nil if this inserter can extract values."
|
||||
'later)
|
||||
|
||||
(cl-defmethod srecode-inserter-extract ((ins srecode-template-inserter-variable)
|
||||
start end vdict state)
|
||||
start end vdict _state)
|
||||
"Extract text from START/END and store in VDICT.
|
||||
Return t if something was extracted.
|
||||
Return nil if this inserter doesn't need to extract anything."
|
||||
|
|
@ -168,12 +168,12 @@ Return nil if this inserter doesn't need to extract anything."
|
|||
|
||||
;;; Section Inserter
|
||||
;;
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((ins srecode-template-inserter-section-start))
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((_ins srecode-template-inserter-section-start))
|
||||
"Return non-nil if this inserter can extract values."
|
||||
'now)
|
||||
|
||||
(cl-defmethod srecode-inserter-extract ((ins srecode-template-inserter-section-start)
|
||||
start end indict state)
|
||||
_start _end indict state)
|
||||
"Extract text from START/END and store in INDICT.
|
||||
Return the starting location of the first plain-text match.
|
||||
Return nil if nothing was extracted."
|
||||
|
|
@ -201,12 +201,12 @@ Return nil if nothing was extracted."
|
|||
|
||||
;;; Include Extractor must extract now.
|
||||
;;
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((ins srecode-template-inserter-include))
|
||||
(cl-defmethod srecode-inserter-do-extract-p ((_ins srecode-template-inserter-include))
|
||||
"Return non-nil if this inserter can extract values."
|
||||
'now)
|
||||
|
||||
(cl-defmethod srecode-inserter-extract ((ins srecode-template-inserter-include)
|
||||
start end dict state)
|
||||
start _end dict state)
|
||||
"Extract text from START/END and store in DICT.
|
||||
Return the starting location of the first plain-text match.
|
||||
Return nil if nothing was extracted."
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/fields.el --- Handling type-in fields in a buffer.
|
||||
;;; srecode/fields.el --- Handling type-in fields in a buffer. -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
|
||||
;;
|
||||
|
|
@ -193,7 +193,7 @@ If SET-TO is a string, then replace the text of OLAID with SET-TO."
|
|||
"Manage a buffer region in which fields exist.")
|
||||
|
||||
(cl-defmethod initialize-instance ((ir srecode-template-inserted-region)
|
||||
&rest args)
|
||||
&rest _args)
|
||||
"Initialize IR, capturing the active fields, and creating the overlay."
|
||||
;; Fill in the fields
|
||||
(oset ir fields srecode-field-archive)
|
||||
|
|
@ -221,7 +221,7 @@ If SET-TO is a string, then replace the text of OLAID with SET-TO."
|
|||
(oset ir active-region ir)
|
||||
|
||||
;; Setup the post command hook.
|
||||
(add-hook 'post-command-hook 'srecode-field-post-command t t)
|
||||
(add-hook 'post-command-hook #'srecode-field-post-command t t)
|
||||
)
|
||||
|
||||
(cl-defmethod srecode-delete ((ir srecode-template-inserted-region))
|
||||
|
|
@ -229,12 +229,11 @@ If SET-TO is a string, then replace the text of OLAID with SET-TO."
|
|||
;; Clear us out of the baseclass.
|
||||
(oset ir active-region nil)
|
||||
;; Clear our fields.
|
||||
(mapc 'srecode-delete (oref ir fields))
|
||||
(mapc #'srecode-delete (oref ir fields))
|
||||
;; Call to our base
|
||||
(cl-call-next-method)
|
||||
;; Clear our hook.
|
||||
(remove-hook 'post-command-hook 'srecode-field-post-command t)
|
||||
)
|
||||
(remove-hook 'post-command-hook #'srecode-field-post-command t))
|
||||
|
||||
(defsubst srecode-active-template-region ()
|
||||
"Return the active region for template fields."
|
||||
|
|
@ -246,7 +245,7 @@ If SET-TO is a string, then replace the text of OLAID with SET-TO."
|
|||
)
|
||||
(if (not ar)
|
||||
;; Find a bug and fix it.
|
||||
(remove-hook 'post-command-hook 'srecode-field-post-command t)
|
||||
(remove-hook 'post-command-hook #'srecode-field-post-command t)
|
||||
(if (srecode-point-in-region-p ar)
|
||||
nil ;; Keep going
|
||||
;; We moved out of the template. Cancel the edits.
|
||||
|
|
@ -277,16 +276,16 @@ Try to use this to provide useful completion when available.")
|
|||
|
||||
(defvar srecode-field-keymap
|
||||
(let ((km (make-sparse-keymap)))
|
||||
(define-key km "\C-i" 'srecode-field-next)
|
||||
(define-key km "\M-\C-i" 'srecode-field-prev)
|
||||
(define-key km "\C-e" 'srecode-field-end)
|
||||
(define-key km "\C-a" 'srecode-field-start)
|
||||
(define-key km "\M-m" 'srecode-field-start)
|
||||
(define-key km "\C-c\C-c" 'srecode-field-exit-ask)
|
||||
(define-key km "\C-i" #'srecode-field-next)
|
||||
(define-key km "\M-\C-i" #'srecode-field-prev)
|
||||
(define-key km "\C-e" #'srecode-field-end)
|
||||
(define-key km "\C-a" #'srecode-field-start)
|
||||
(define-key km "\M-m" #'srecode-field-start)
|
||||
(define-key km "\C-c\C-c" #'srecode-field-exit-ask)
|
||||
km)
|
||||
"Keymap applied to field overlays.")
|
||||
|
||||
(cl-defmethod initialize-instance ((field srecode-field) &optional args)
|
||||
(cl-defmethod initialize-instance ((field srecode-field) &optional _args)
|
||||
"Initialize FIELD, being sure it archived."
|
||||
(add-to-list 'srecode-field-archive field t)
|
||||
(cl-call-next-method)
|
||||
|
|
@ -327,7 +326,7 @@ Try to use this to provide useful completion when available.")
|
|||
(defvar srecode-field-replication-max-size 100
|
||||
"Maximum size of a field before canceling replication.")
|
||||
|
||||
(defun srecode-field-mod-hook (ol after start end &optional pre-len)
|
||||
(defun srecode-field-mod-hook (ol after _start _end &optional _pre-len)
|
||||
"Modification hook for the field overlay.
|
||||
OL is the overlay.
|
||||
AFTER is non-nil if it is called after the change.
|
||||
|
|
@ -374,7 +373,7 @@ AFTER is non-nil if it is called after the change.
|
|||
START and END are the bounds of the change.
|
||||
PRE-LEN is used in the after mode for the length of the changed text."
|
||||
(when after
|
||||
(let* ((field (overlay-get ol 'srecode))
|
||||
(let* (;; (field (overlay-get ol 'srecode))
|
||||
)
|
||||
(move-overlay ol (overlay-start ol) end)
|
||||
(srecode-field-mod-hook ol after start end pre-len))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/filters.el --- Filters for use in template variables.
|
||||
;;; srecode/filters.el --- Filters for use in template variables. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;;; srecode/find.el --- Tools for finding templates in the database.
|
||||
;;;; srecode/find.el --- Tools for finding templates in the database. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -58,17 +58,14 @@ See `srecode-get-maps' for more.
|
|||
APPNAME is the name of an application. In this case,
|
||||
all template files for that application will be loaded."
|
||||
(let ((files
|
||||
(if appname
|
||||
(apply 'append
|
||||
(mapcar
|
||||
(apply #'append
|
||||
(mapcar
|
||||
(if appname
|
||||
(lambda (map)
|
||||
(srecode-map-entries-for-app-and-mode map appname mmode))
|
||||
(srecode-get-maps)))
|
||||
(apply 'append
|
||||
(mapcar
|
||||
(lambda (map)
|
||||
(srecode-map-entries-for-mode map mmode))
|
||||
(srecode-get-maps)))))
|
||||
(srecode-map-entries-for-mode map mmode)))
|
||||
(srecode-get-maps))))
|
||||
)
|
||||
;; Don't recurse if we are already the 'default state.
|
||||
(when (not (eq mmode 'default))
|
||||
|
|
@ -112,8 +109,8 @@ If TAB is nil, then always return t."
|
|||
;; Find a given template based on name, and features of the current
|
||||
;; buffer.
|
||||
(cl-defmethod srecode-template-get-table ((tab srecode-template-table)
|
||||
template-name &optional
|
||||
context application)
|
||||
template-name &optional
|
||||
context _application)
|
||||
"Find in the template in table TAB, the template with TEMPLATE-NAME.
|
||||
Optional argument CONTEXT specifies that the template should part
|
||||
of a particular context.
|
||||
|
|
@ -218,7 +215,7 @@ tables that do not belong to an application will be searched."
|
|||
(defvar srecode-read-template-name-history nil
|
||||
"History for completing reads for template names.")
|
||||
|
||||
(defun srecode-user-template-p (template)
|
||||
(defun srecode-user-template-p (_template)
|
||||
"Non-nil if TEMPLATE is intended for user insertion.
|
||||
Templates not matching this predicate are used for code
|
||||
generation or other internal purposes."
|
||||
|
|
@ -264,7 +261,7 @@ with `srecode-calculate-context'."
|
|||
;; the prefix for the completing read
|
||||
(concat (nth 0 ctxt) ":"))))
|
||||
|
||||
(defun srecode-read-template-name (prompt &optional initial hist default)
|
||||
(defun srecode-read-template-name (prompt &optional initial hist _default)
|
||||
"Completing read for Semantic Recoder template names.
|
||||
PROMPT is used to query for the name of the template desired.
|
||||
INITIAL is the initial string to use.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/getset.el --- Package for inserting new get/set methods.
|
||||
;;; srecode/getset.el --- Package for inserting new get/set methods. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -33,6 +33,8 @@
|
|||
(defvar srecode-insert-getset-fully-automatic-flag nil
|
||||
"Non-nil means accept choices srecode comes up with without asking.")
|
||||
|
||||
(defvar srecode-semantic-selected-tag)
|
||||
|
||||
;;;###autoload
|
||||
(defun srecode-insert-getset (&optional class-in field-in)
|
||||
"Insert get/set methods for the current class.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/java.el --- Srecode Java support
|
||||
;;; srecode/java.el --- Srecode Java support -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/map.el --- Manage a template file map
|
||||
;;; srecode/map.el --- Manage a template file map -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ Optional argument RESET forces a reset of the current map."
|
|||
(princ "\n")
|
||||
))
|
||||
|
||||
(defun srecode-map-file-still-valid-p (filename map)
|
||||
(defun srecode-map-file-still-valid-p (filename _map)
|
||||
"Return t if FILENAME should be in MAP still."
|
||||
(let ((valid nil))
|
||||
(and (file-exists-p filename)
|
||||
|
|
@ -407,7 +407,7 @@ Return non-nil if the map changed."
|
|||
"Global load path for SRecode template files."
|
||||
:group 'srecode
|
||||
:type '(repeat file)
|
||||
:set 'srecode-map-load-path-set)
|
||||
:set #'srecode-map-load-path-set)
|
||||
|
||||
(provide 'srecode/map)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/mode.el --- Minor mode for managing and using SRecode templates
|
||||
;;; srecode/mode.el --- Minor mode for managing and using SRecode templates -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -54,14 +54,14 @@
|
|||
(defvar srecode-prefix-map
|
||||
(let ((km (make-sparse-keymap)))
|
||||
;; Basic template codes
|
||||
(define-key km "/" 'srecode-insert)
|
||||
(define-key km [insert] 'srecode-insert)
|
||||
(define-key km "." 'srecode-insert-again)
|
||||
(define-key km "E" 'srecode-edit)
|
||||
(define-key km "/" #'srecode-insert)
|
||||
(define-key km [insert] #'srecode-insert)
|
||||
(define-key km "." #'srecode-insert-again)
|
||||
(define-key km "E" #'srecode-edit)
|
||||
;; Template indirect binding
|
||||
(let ((k ?a))
|
||||
(while (<= k ?z)
|
||||
(define-key km (format "%c" k) 'srecode-bind-insert)
|
||||
(define-key km (format "%c" k) #'srecode-bind-insert)
|
||||
(setq k (1+ k))))
|
||||
km)
|
||||
"Keymap used behind the srecode prefix key in srecode minor mode.")
|
||||
|
|
@ -141,16 +141,17 @@ non-nil if the minor mode is enabled.
|
|||
;; this mode first.
|
||||
(if srecode-minor-mode
|
||||
(if (not (apply
|
||||
'append
|
||||
#'append
|
||||
(mapcar (lambda (map)
|
||||
(srecode-map-entries-for-mode map major-mode))
|
||||
(srecode-get-maps))))
|
||||
(setq srecode-minor-mode nil)
|
||||
;; Else, we have success, do stuff
|
||||
(add-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items nil t)
|
||||
)
|
||||
(remove-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items t)
|
||||
)
|
||||
;; FIXME: Where are `cedet-m3-menu-do-hooks' nor `srecode-m3-items'?
|
||||
(when (fboundp 'srecode-m3-items)
|
||||
(add-hook 'cedet-m3-menu-do-hooks #'srecode-m3-items nil t)))
|
||||
(when (fboundp 'srecode-m3-items)
|
||||
(remove-hook 'cedet-m3-menu-do-hooks #'srecode-m3-items t)))
|
||||
;; Run hooks if we are turning this on.
|
||||
(when srecode-minor-mode
|
||||
(run-hooks 'srecode-minor-mode-hook))
|
||||
|
|
@ -170,7 +171,7 @@ non-nil if the minor mode is enabled.
|
|||
|
||||
;;; Menu Filters
|
||||
;;
|
||||
(defun srecode-minor-mode-templates-menu (menu-def)
|
||||
(defun srecode-minor-mode-templates-menu (_menu-def)
|
||||
"Create a menu item of cascading filters active for this mode.
|
||||
MENU-DEF is the menu to bind this into."
|
||||
;; Doing this SEGVs Emacs on windows.
|
||||
|
|
@ -246,7 +247,7 @@ MENU-DEF is the menu to bind this into."
|
|||
(defvar srecode-minor-mode-generators nil
|
||||
"List of code generators to be displayed in the srecoder menu.")
|
||||
|
||||
(defun srecode-minor-mode-generate-menu (menu-def)
|
||||
(defun srecode-minor-mode-generate-menu (_menu-def)
|
||||
"Create a menu item of cascading filters active for this mode.
|
||||
MENU-DEF is the menu to bind this into."
|
||||
;; Doing this SEGVs Emacs on windows.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/srt-mode.el --- Major mode for writing screcode macros
|
||||
;;; srecode/srt-mode.el --- Major mode for writing screcode macros -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -181,9 +181,9 @@ we can tell font lock about them.")
|
|||
|
||||
(defvar srecode-template-mode-map
|
||||
(let ((km (make-sparse-keymap)))
|
||||
(define-key km "\C-c\C-c" 'srecode-compile-templates)
|
||||
(define-key km "\C-c\C-m" 'srecode-macro-help)
|
||||
(define-key km "/" 'srecode-self-insert-complete-end-macro)
|
||||
(define-key km "\C-c\C-c" #'srecode-compile-templates)
|
||||
(define-key km "\C-c\C-m" #'srecode-macro-help)
|
||||
(define-key km "/" #'srecode-self-insert-complete-end-macro)
|
||||
km)
|
||||
"Keymap used in srecode mode.")
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ we can tell font lock about them.")
|
|||
((?_ . "w") (?- . "w")))))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'srt-mode 'srecode-template-mode)
|
||||
(defalias 'srt-mode #'srecode-template-mode)
|
||||
|
||||
;;; Template Commands
|
||||
;;
|
||||
|
|
@ -436,7 +436,7 @@ Moves to the end of one named section."
|
|||
(when point (goto-char (point)))
|
||||
(let* ((tag (semantic-current-tag))
|
||||
(args (semantic-tag-function-arguments tag))
|
||||
(argsym (mapcar 'intern args))
|
||||
(argsym (mapcar #'intern args))
|
||||
(argvars nil)
|
||||
;; Create a temporary dictionary in which the
|
||||
;; arguments can be resolved so we can extract
|
||||
|
|
@ -475,7 +475,7 @@ section or ? for an ask variable."
|
|||
(ee (regexp-quote (srecode-template-get-escape-end)))
|
||||
(start (point))
|
||||
(macrostart nil)
|
||||
(raw nil)
|
||||
;; (raw nil)
|
||||
)
|
||||
(when (and tag (semantic-tag-of-class-p tag 'function)
|
||||
(srecode-in-macro-p point)
|
||||
|
|
@ -627,7 +627,7 @@ section or ? for an ask variable."
|
|||
context-return)))
|
||||
|
||||
(define-mode-local-override semantic-analyze-possible-completions
|
||||
srecode-template-mode (context &rest flags)
|
||||
srecode-template-mode (context &rest _flags)
|
||||
"Return a list of possible completions based on NONTEXT."
|
||||
(with-current-buffer (oref context buffer)
|
||||
(let* ((prefix (car (last (oref context prefix))))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/srt.el --- argument handlers for SRT files
|
||||
;;; srecode/srt.el --- argument handlers for SRT files -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ DEFAULT is the default if RET is hit."
|
|||
(currfcn (semantic-current-tag))
|
||||
)
|
||||
(srecode-resolve-argument-list
|
||||
(mapcar 'read
|
||||
(mapcar #'read
|
||||
(semantic-tag-get-attribute currfcn :arguments))
|
||||
newdict)
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ DEFAULT is the default if RET is hit."
|
|||
(defvar srecode-read-major-mode-history nil
|
||||
"History for `srecode-read-variable-name'.")
|
||||
|
||||
(defun srecode-read-major-mode-name (prompt &optional initial hist default)
|
||||
(defun srecode-read-major-mode-name (prompt &optional initial hist _default)
|
||||
"Read in the name of a desired `major-mode'.
|
||||
PROMPT is the prompt to use.
|
||||
INITIAL is the initial string.
|
||||
|
|
@ -64,7 +64,7 @@ HIST is the history value, otherwise `srecode-read-variable-name-history'
|
|||
is used.
|
||||
DEFAULT is the default if RET is hit."
|
||||
(completing-read prompt obarray
|
||||
(lambda (s) (string-match "-mode$" (symbol-name s)))
|
||||
(lambda (s) (string-match "-mode\\'" (symbol-name s)))
|
||||
nil initial (or hist 'srecode-read-major-mode-history))
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/table.el --- Tables of Semantic Recoders
|
||||
;;; srecode/table.el --- Tables of Semantic Recoders -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ calculate all inherited templates from parent modes."
|
|||
:modetables nil
|
||||
:tables nil)))
|
||||
;; Save this new mode table in that mode's variable.
|
||||
(eval `(setq-mode-local ,mode srecode-table ,new))
|
||||
(eval `(setq-mode-local ,mode srecode-table ,new) t)
|
||||
|
||||
new))))
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ INIT are the initialization parameters for the new template table."
|
|||
(let* ((mt (srecode-make-mode-table mode))
|
||||
(old (srecode-mode-table-find mt file))
|
||||
(attr (file-attributes file))
|
||||
(new (apply 'srecode-template-table
|
||||
(new (apply #'srecode-template-table
|
||||
(file-name-nondirectory file)
|
||||
:file file
|
||||
:filesize (file-attribute-size attr)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/template.el --- SRecoder template language parser support.
|
||||
;;; srecode/template.el --- SRecoder template language parser support. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; srecode/texi.el --- Srecode texinfo support.
|
||||
;;; srecode/texi.el --- Srecode texinfo support. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ Takes a few very generic guesses as to what the formatting is."
|
|||
;; Return our modified doc string.
|
||||
docstring))
|
||||
|
||||
(defun srecode-texi-massage-to-texinfo (tag buffer string)
|
||||
(defun srecode-texi-massage-to-texinfo (_tag buffer string)
|
||||
"Massage TAG's documentation from BUFFER as STRING.
|
||||
This is to take advantage of TeXinfo's markup symbols."
|
||||
(save-excursion
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
(defun minibuffer-prompt-properties--setter (symbol value)
|
||||
(set-default symbol value)
|
||||
(if (memq 'cursor-intangible value)
|
||||
(add-hook 'minibuffer-setup-hook 'cursor-intangible-mode)
|
||||
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
|
||||
;; Removing it is a bit trickier since it could have been added by someone
|
||||
;; else as well, so let's just not bother.
|
||||
))
|
||||
|
|
|
|||
|
|
@ -1200,6 +1200,32 @@ property `theme-feature' (which is usually a symbol created by
|
|||
(custom-check-theme theme)
|
||||
(provide (get theme 'theme-feature)))
|
||||
|
||||
(defun require-theme (feature &optional noerror)
|
||||
"Load FEATURE from a file along `custom-theme-load-path'.
|
||||
|
||||
This function is like `require', but searches along
|
||||
`custom-theme-load-path' instead of `load-path'. It can be used
|
||||
by Custom themes to load supporting Lisp files when `require' is
|
||||
unsuitable.
|
||||
|
||||
If FEATURE is not already loaded, search for a file named FEATURE
|
||||
with an added `.elc' or `.el' suffix, in that order, in the
|
||||
directories specified by `custom-theme-load-path'.
|
||||
|
||||
Return FEATURE if the file is successfully found and loaded, or
|
||||
if FEATURE was already loaded. If the file fails to load, signal
|
||||
an error. If optional argument NOERROR is non-nil, return nil
|
||||
instead of signaling an error. If the file loads but does not
|
||||
provide FEATURE, signal an error. This cannot be suppressed."
|
||||
(cond
|
||||
((featurep feature) feature)
|
||||
((let* ((path (custom-theme--load-path))
|
||||
(file (locate-file (symbol-name feature) path '(".elc" ".el"))))
|
||||
(and file (require feature (file-name-sans-extension file) noerror))))
|
||||
((not noerror)
|
||||
(signal 'file-missing `("Cannot open load file" "No such file or directory"
|
||||
,(symbol-name feature))))))
|
||||
|
||||
(defcustom custom-safe-themes '(default)
|
||||
"Themes that are considered safe to load.
|
||||
If the value is a list, each element should be either the SHA-256
|
||||
|
|
|
|||
|
|
@ -1072,8 +1072,13 @@ To kill an entire subdirectory \(without killing its line in the
|
|||
parent directory), go to its directory header line and use this
|
||||
command with a prefix argument (the value does not matter).
|
||||
|
||||
To undo the killing, the undo command can be used as normally."
|
||||
;; Returns count of killed lines. FMT="" suppresses message.
|
||||
To undo the killing, the undo command can be used as normally.
|
||||
|
||||
This function returns the number of killed lines.
|
||||
|
||||
FMT is a format string used for messaging the user about the
|
||||
killed lines, and defaults to \"Killed %d line%s.\" if not
|
||||
present. A FMT of \"\" will suppress the messaging."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(if (dired-get-subdir)
|
||||
|
|
|
|||
|
|
@ -236,8 +236,6 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
|
|||
|
||||
;;; MENU BINDINGS
|
||||
|
||||
(require 'easymenu)
|
||||
|
||||
(when-let ((menu (lookup-key dired-mode-map [menu-bar])))
|
||||
(easy-menu-add-item menu '("Operate")
|
||||
["Find Files" dired-do-find-marked-files
|
||||
|
|
|
|||
522
lisp/dired.el
522
lisp/dired.el
|
|
@ -1966,328 +1966,217 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
|
|||
(define-key map ":s" 'epa-dired-do-sign)
|
||||
(define-key map ":e" 'epa-dired-do-encrypt)
|
||||
|
||||
;; Make menu bar items.
|
||||
|
||||
;; No need to do this, now that top-level items are fewer.
|
||||
;;;;
|
||||
;; Get rid of the Edit menu bar item to save space.
|
||||
;(define-key map [menu-bar edit] 'undefined)
|
||||
|
||||
(define-key map [menu-bar subdir]
|
||||
(cons "Subdir" (make-sparse-keymap "Subdir")))
|
||||
|
||||
(define-key map [menu-bar subdir hide-all]
|
||||
'(menu-item "Hide All" dired-hide-all
|
||||
:help "Hide all subdirectories, leave only header lines"))
|
||||
(define-key map [menu-bar subdir hide-subdir]
|
||||
'(menu-item "Hide/UnHide Subdir" dired-hide-subdir
|
||||
:help "Hide or unhide current directory listing"))
|
||||
(define-key map [menu-bar subdir tree-down]
|
||||
'(menu-item "Tree Down" dired-tree-down
|
||||
:help "Go to first subdirectory header down the tree"))
|
||||
(define-key map [menu-bar subdir tree-up]
|
||||
'(menu-item "Tree Up" dired-tree-up
|
||||
:help "Go to first subdirectory header up the tree"))
|
||||
(define-key map [menu-bar subdir up]
|
||||
'(menu-item "Up Directory" dired-up-directory
|
||||
:help "Edit the parent directory"))
|
||||
(define-key map [menu-bar subdir prev-subdir]
|
||||
'(menu-item "Prev Subdir" dired-prev-subdir
|
||||
:help "Go to previous subdirectory header line"))
|
||||
(define-key map [menu-bar subdir next-subdir]
|
||||
'(menu-item "Next Subdir" dired-next-subdir
|
||||
:help "Go to next subdirectory header line"))
|
||||
(define-key map [menu-bar subdir prev-dirline]
|
||||
'(menu-item "Prev Dirline" dired-prev-dirline
|
||||
:help "Move to next directory-file line"))
|
||||
(define-key map [menu-bar subdir next-dirline]
|
||||
'(menu-item "Next Dirline" dired-next-dirline
|
||||
:help "Move to previous directory-file line"))
|
||||
(define-key map [menu-bar subdir insert]
|
||||
'(menu-item "Insert This Subdir" dired-maybe-insert-subdir
|
||||
:help "Insert contents of subdirectory"
|
||||
:enable (let ((f (dired-get-filename nil t)))
|
||||
(and f (file-directory-p f)))))
|
||||
(define-key map [menu-bar immediate]
|
||||
(cons "Immediate" (make-sparse-keymap "Immediate")))
|
||||
|
||||
(define-key map
|
||||
[menu-bar immediate image-dired-dired-display-external]
|
||||
'(menu-item "Display Image Externally" image-dired-dired-display-external
|
||||
:help "Display image in external viewer"))
|
||||
(define-key map
|
||||
[menu-bar immediate image-dired-dired-display-image]
|
||||
'(menu-item "Display Image" image-dired-dired-display-image
|
||||
:help "Display sized image in a separate window"))
|
||||
(define-key map
|
||||
[menu-bar immediate image-dired-dired-toggle-marked-thumbs]
|
||||
'(menu-item "Toggle Image Thumbnails in This Buffer" image-dired-dired-toggle-marked-thumbs
|
||||
:help "Add or remove image thumbnails in front of marked file names"))
|
||||
|
||||
(define-key map [menu-bar immediate hide-details]
|
||||
'(menu-item "Hide Details" dired-hide-details-mode
|
||||
:help "Hide details in buffer"
|
||||
:button (:toggle . dired-hide-details-mode)))
|
||||
(define-key map [menu-bar immediate revert-buffer]
|
||||
'(menu-item "Refresh" revert-buffer
|
||||
:help "Update contents of shown directories"))
|
||||
(define-key map [menu-bar immediate dired-number-of-marked-files]
|
||||
'(menu-item "#Marked Files" dired-number-of-marked-files
|
||||
:help "Display the number and size of the marked files"))
|
||||
|
||||
(define-key map [menu-bar immediate dashes]
|
||||
'("--"))
|
||||
|
||||
(define-key map [menu-bar immediate isearch-filenames-regexp]
|
||||
'(menu-item "Isearch Regexp in File Names..." dired-isearch-filenames-regexp
|
||||
:help "Incrementally search for regexp in file names only"))
|
||||
(define-key map [menu-bar immediate isearch-filenames]
|
||||
'(menu-item "Isearch in File Names..." dired-isearch-filenames
|
||||
:help "Incrementally search for string in file names only."))
|
||||
(define-key map [menu-bar immediate compare-directories]
|
||||
'(menu-item "Compare Directories..." dired-compare-directories
|
||||
:help "Mark files with different attributes in two Dired buffers"))
|
||||
(define-key map [menu-bar immediate backup-diff]
|
||||
'(menu-item "Compare with Backup" dired-backup-diff
|
||||
:help "Diff file at cursor with its latest backup"))
|
||||
(define-key map [menu-bar immediate diff]
|
||||
'(menu-item "Diff..." dired-diff
|
||||
:help "Compare file at cursor with another file"))
|
||||
(define-key map [menu-bar immediate view]
|
||||
'(menu-item "View This File" dired-view-file
|
||||
:help "Examine file at cursor in read-only mode"))
|
||||
(define-key map [menu-bar immediate display]
|
||||
'(menu-item "Display in Other Window" dired-display-file
|
||||
:help "Display file at cursor in other window"))
|
||||
(define-key map [menu-bar immediate find-file-other-window]
|
||||
'(menu-item "Find in Other Window" dired-find-file-other-window
|
||||
:help "Edit file at cursor in other window"))
|
||||
(define-key map [menu-bar immediate find-file]
|
||||
'(menu-item "Find This File" dired-find-file
|
||||
:help "Edit file at cursor"))
|
||||
(define-key map [menu-bar immediate create-directory]
|
||||
'(menu-item "Create Directory..." dired-create-directory
|
||||
:help "Create a directory"))
|
||||
(define-key map [menu-bar immediate create-empty-file]
|
||||
'(menu-item "Create Empty file..." dired-create-empty-file
|
||||
:help "Create an empty file"))
|
||||
(define-key map [menu-bar immediate wdired-mode]
|
||||
'(menu-item "Edit File Names" wdired-change-to-wdired-mode
|
||||
:help "Put a Dired buffer in a mode in which filenames are editable"
|
||||
:keys "C-x C-q"
|
||||
:filter (lambda (x) (if (eq major-mode 'dired-mode) x))))
|
||||
|
||||
(define-key map [menu-bar regexp]
|
||||
(cons "Regexp" (make-sparse-keymap "Regexp")))
|
||||
|
||||
(define-key map
|
||||
[menu-bar regexp image-dired-mark-tagged-files]
|
||||
'(menu-item "Mark From Image Tag..." image-dired-mark-tagged-files
|
||||
:help "Mark files whose image tags matches regexp"))
|
||||
|
||||
(define-key map [menu-bar regexp dashes-1]
|
||||
'("--"))
|
||||
|
||||
(define-key map [menu-bar regexp downcase]
|
||||
'(menu-item "Downcase" dired-downcase
|
||||
;; When running on plain MS-DOS, there's only one
|
||||
;; letter-case for file names.
|
||||
:enable (or (not (fboundp 'msdos-long-file-names))
|
||||
(msdos-long-file-names))
|
||||
:help "Rename marked files to lower-case name"))
|
||||
(define-key map [menu-bar regexp upcase]
|
||||
'(menu-item "Upcase" dired-upcase
|
||||
:enable (or (not (fboundp 'msdos-long-file-names))
|
||||
(msdos-long-file-names))
|
||||
:help "Rename marked files to upper-case name"))
|
||||
(define-key map [menu-bar regexp hardlink]
|
||||
'(menu-item "Hardlink..." dired-do-hardlink-regexp
|
||||
:help "Make hard links for files matching regexp"))
|
||||
(define-key map [menu-bar regexp symlink]
|
||||
'(menu-item "Symlink..." dired-do-symlink-regexp
|
||||
:visible (fboundp 'make-symbolic-link)
|
||||
:help "Make symbolic links for files matching regexp"))
|
||||
(define-key map [menu-bar regexp rename]
|
||||
'(menu-item "Rename..." dired-do-rename-regexp
|
||||
:help "Rename marked files matching regexp"))
|
||||
(define-key map [menu-bar regexp copy]
|
||||
'(menu-item "Copy..." dired-do-copy-regexp
|
||||
:help "Copy marked files matching regexp"))
|
||||
(define-key map [menu-bar regexp flag]
|
||||
'(menu-item "Flag..." dired-flag-files-regexp
|
||||
:help "Flag files matching regexp for deletion"))
|
||||
(define-key map [menu-bar regexp mark]
|
||||
'(menu-item "Mark..." dired-mark-files-regexp
|
||||
:help "Mark files matching regexp for future operations"))
|
||||
(define-key map [menu-bar regexp mark-cont]
|
||||
'(menu-item "Mark Containing..." dired-mark-files-containing-regexp
|
||||
:help "Mark files whose contents matches regexp"))
|
||||
|
||||
(define-key map [menu-bar mark]
|
||||
(cons "Mark" (make-sparse-keymap "Mark")))
|
||||
|
||||
(define-key map [menu-bar mark prev]
|
||||
'(menu-item "Previous Marked" dired-prev-marked-file
|
||||
:help "Move to previous marked file"))
|
||||
(define-key map [menu-bar mark next]
|
||||
'(menu-item "Next Marked" dired-next-marked-file
|
||||
:help "Move to next marked file"))
|
||||
(define-key map [menu-bar mark marks]
|
||||
'(menu-item "Change Marks..." dired-change-marks
|
||||
:help "Replace marker with another character"))
|
||||
(define-key map [menu-bar mark unmark-all]
|
||||
'(menu-item "Unmark All" dired-unmark-all-marks))
|
||||
(define-key map [menu-bar mark symlinks]
|
||||
'(menu-item "Mark Symlinks" dired-mark-symlinks
|
||||
:visible (fboundp 'make-symbolic-link)
|
||||
:help "Mark all symbolic links"))
|
||||
(define-key map [menu-bar mark directories]
|
||||
'(menu-item "Mark Directories" dired-mark-directories
|
||||
:help "Mark all directories except `.' and `..'"))
|
||||
(define-key map [menu-bar mark directory]
|
||||
'(menu-item "Mark Old Backups" dired-clean-directory
|
||||
:help "Flag old numbered backups for deletion"))
|
||||
(define-key map [menu-bar mark executables]
|
||||
'(menu-item "Mark Executables" dired-mark-executables
|
||||
:help "Mark all executable files"))
|
||||
(define-key map [menu-bar mark garbage-files]
|
||||
'(menu-item "Flag Garbage Files" dired-flag-garbage-files
|
||||
:help "Flag unneeded files for deletion"))
|
||||
(define-key map [menu-bar mark backup-files]
|
||||
'(menu-item "Flag Backup Files" dired-flag-backup-files
|
||||
:help "Flag all backup files for deletion"))
|
||||
(define-key map [menu-bar mark auto-save-files]
|
||||
'(menu-item "Flag Auto-save Files" dired-flag-auto-save-files
|
||||
:help "Flag auto-save files for deletion"))
|
||||
(define-key map [menu-bar mark deletion]
|
||||
'(menu-item "Flag" dired-flag-file-deletion
|
||||
:help "Flag current line's file for deletion"))
|
||||
(define-key map [menu-bar mark unmark]
|
||||
'(menu-item "Unmark" dired-unmark
|
||||
:help "Unmark or unflag current line's file"))
|
||||
(define-key map [menu-bar mark mark]
|
||||
'(menu-item "Mark" dired-mark
|
||||
:help "Mark current line's file for future operations"))
|
||||
(define-key map [menu-bar mark toggle-marks]
|
||||
'(menu-item "Toggle Marks" dired-toggle-marks
|
||||
:help "Mark unmarked files, unmark marked ones"))
|
||||
|
||||
(define-key map [menu-bar operate]
|
||||
(cons "Operate" (make-sparse-keymap "Operate")))
|
||||
|
||||
(define-key map
|
||||
[menu-bar operate image-dired-delete-tag]
|
||||
'(menu-item "Delete Image Tag..." image-dired-delete-tag
|
||||
:help "Delete image tag from current or marked files"))
|
||||
(define-key map
|
||||
[menu-bar operate image-dired-tag-files]
|
||||
'(menu-item "Add Image Tags..." image-dired-tag-files
|
||||
:help "Add image tags to current or marked files"))
|
||||
(define-key map
|
||||
[menu-bar operate image-dired-dired-comment-files]
|
||||
'(menu-item "Add Image Comment..." image-dired-dired-comment-files
|
||||
:help "Add image comment to current or marked files"))
|
||||
(define-key map
|
||||
[menu-bar operate image-dired-display-thumbs]
|
||||
'(menu-item "Display Image Thumbnails" image-dired-display-thumbs
|
||||
:help "Display image thumbnails for current or marked image files"))
|
||||
|
||||
(define-key map [menu-bar operate dashes-4]
|
||||
'("--"))
|
||||
|
||||
(define-key map
|
||||
[menu-bar operate epa-dired-do-decrypt]
|
||||
'(menu-item "Decrypt..." epa-dired-do-decrypt
|
||||
:help "Decrypt current or marked files"))
|
||||
|
||||
(define-key map
|
||||
[menu-bar operate epa-dired-do-verify]
|
||||
'(menu-item "Verify" epa-dired-do-verify
|
||||
:help "Verify digital signature of current or marked files"))
|
||||
|
||||
(define-key map
|
||||
[menu-bar operate epa-dired-do-sign]
|
||||
'(menu-item "Sign..." epa-dired-do-sign
|
||||
:help "Create digital signature of current or marked files"))
|
||||
|
||||
(define-key map
|
||||
[menu-bar operate epa-dired-do-encrypt]
|
||||
'(menu-item "Encrypt..." epa-dired-do-encrypt
|
||||
:help "Encrypt current or marked files"))
|
||||
|
||||
(define-key map [menu-bar operate dashes-3]
|
||||
'("--"))
|
||||
|
||||
(define-key map [menu-bar operate query-replace]
|
||||
'(menu-item "Query Replace in Files..." dired-do-find-regexp-and-replace
|
||||
:help "Replace regexp matches in marked files"))
|
||||
(define-key map [menu-bar operate search]
|
||||
'(menu-item "Search Files..." dired-do-find-regexp
|
||||
:help "Search marked files for matches of regexp"))
|
||||
(define-key map [menu-bar operate isearch-regexp]
|
||||
'(menu-item "Isearch Regexp Files..." dired-do-isearch-regexp
|
||||
:help "Incrementally search marked files for regexp"))
|
||||
(define-key map [menu-bar operate isearch]
|
||||
'(menu-item "Isearch Files..." dired-do-isearch
|
||||
:help "Incrementally search marked files for string"))
|
||||
(define-key map [menu-bar operate chown]
|
||||
'(menu-item "Change Owner..." dired-do-chown
|
||||
:visible (not (memq system-type '(ms-dos windows-nt)))
|
||||
:help "Change the owner of marked files"))
|
||||
(define-key map [menu-bar operate chgrp]
|
||||
'(menu-item "Change Group..." dired-do-chgrp
|
||||
:visible (not (memq system-type '(ms-dos windows-nt)))
|
||||
:help "Change the group of marked files"))
|
||||
(define-key map [menu-bar operate chmod]
|
||||
'(menu-item "Change Mode..." dired-do-chmod
|
||||
:help "Change mode (attributes) of marked files"))
|
||||
(define-key map [menu-bar operate touch]
|
||||
'(menu-item "Change Timestamp..." dired-do-touch
|
||||
:help "Change timestamp of marked files"))
|
||||
(define-key map [menu-bar operate load]
|
||||
'(menu-item "Load" dired-do-load
|
||||
:help "Load marked Emacs Lisp files"))
|
||||
(define-key map [menu-bar operate compile]
|
||||
'(menu-item "Byte-compile" dired-do-byte-compile
|
||||
:help "Byte-compile marked Emacs Lisp files"))
|
||||
(define-key map [menu-bar operate compress]
|
||||
'(menu-item "Compress" dired-do-compress
|
||||
:help "Compress/uncompress marked files"))
|
||||
(define-key map [menu-bar operate print]
|
||||
'(menu-item "Print..." dired-do-print
|
||||
:help "Ask for print command and print marked files"))
|
||||
(define-key map [menu-bar operate hardlink]
|
||||
'(menu-item "Hardlink to..." dired-do-hardlink
|
||||
:help "Make hard links for current or marked files"))
|
||||
(define-key map [menu-bar operate symlink]
|
||||
'(menu-item "Symlink to..." dired-do-symlink
|
||||
:visible (fboundp 'make-symbolic-link)
|
||||
:help "Make symbolic links for current or marked files"))
|
||||
(define-key map [menu-bar operate async-command]
|
||||
'(menu-item "Asynchronous Shell Command..." dired-do-async-shell-command
|
||||
:help "Run a shell command asynchronously on current or marked files"))
|
||||
(define-key map [menu-bar operate command]
|
||||
'(menu-item "Shell Command..." dired-do-shell-command
|
||||
:help "Run a shell command on current or marked files"))
|
||||
(define-key map [menu-bar operate delete]
|
||||
`(menu-item "Delete"
|
||||
,(let ((menu (make-sparse-keymap "Delete")))
|
||||
(define-key menu [delete-flagged]
|
||||
'(menu-item "Delete Flagged Files" dired-do-flagged-delete
|
||||
:help "Delete all files flagged for deletion (D)"))
|
||||
(define-key menu [delete-marked]
|
||||
'(menu-item "Delete Marked (Not Flagged) Files" dired-do-delete
|
||||
:help "Delete current file or all marked files (excluding flagged files)"))
|
||||
menu)))
|
||||
(define-key map [menu-bar operate rename]
|
||||
'(menu-item "Rename to..." dired-do-rename
|
||||
:help "Rename current file or move marked files"))
|
||||
(define-key map [menu-bar operate copy]
|
||||
'(menu-item "Copy to..." dired-do-copy
|
||||
:help "Copy current file or all marked files"))
|
||||
|
||||
map)
|
||||
"Local keymap for Dired mode buffers.")
|
||||
|
||||
(easy-menu-define dired-mode-subdir-menu dired-mode-map
|
||||
"Subdir menu for Dired mode."
|
||||
'("Subdir"
|
||||
["Insert This Subdir" dired-maybe-insert-subdir
|
||||
:help "Insert contents of subdirectory"
|
||||
:enable (let ((f (dired-get-filename nil t)))
|
||||
(and f (file-directory-p f)))]
|
||||
["Next Dirline" dired-next-dirline
|
||||
:help "Move to previous directory-file line"]
|
||||
["Prev Dirline" dired-prev-dirline
|
||||
:help "Move to next directory-file line"]
|
||||
["Next Subdir" dired-next-subdir
|
||||
:help "Go to next subdirectory header line"]
|
||||
["Prev Subdir" dired-prev-subdir
|
||||
:help "Go to previous subdirectory header line"]
|
||||
["Up Directory" dired-up-directory
|
||||
:help "Edit the parent directory"]
|
||||
["Tree Up" dired-tree-up
|
||||
:help "Go to first subdirectory header up the tree"]
|
||||
["Tree Down" dired-tree-down
|
||||
:help "Go to first subdirectory header down the tree"]
|
||||
["Hide/UnHide Subdir" dired-hide-subdir
|
||||
:help "Hide or unhide current directory listing"]
|
||||
["Hide All" dired-hide-all
|
||||
:help "Hide all subdirectories, leave only header lines"]))
|
||||
|
||||
(easy-menu-define dired-mode-immediate-menu dired-mode-map
|
||||
"Immediate menu for Dired mode."
|
||||
'("Immediate"
|
||||
["Edit File Names" wdired-change-to-wdired-mode
|
||||
:help "Put a Dired buffer in a mode in which filenames are editable"
|
||||
:keys "C-x C-q"
|
||||
:filter (lambda (x) (if (eq major-mode 'dired-mode) x))]
|
||||
["Create Empty file..." dired-create-empty-file
|
||||
:help "Create an empty file"]
|
||||
["Create Directory..." dired-create-directory
|
||||
:help "Create a directory"]
|
||||
["Find This File" dired-find-file
|
||||
:help "Edit file at cursor"]
|
||||
["Find in Other Window" dired-find-file-other-window
|
||||
:help "Edit file at cursor in other window"]
|
||||
["Display in Other Window" dired-display-file
|
||||
:help "Display file at cursor in other window"]
|
||||
["View This File" dired-view-file
|
||||
:help "Examine file at cursor in read-only mode"]
|
||||
["Diff..." dired-diff
|
||||
:help "Compare file at cursor with another file"]
|
||||
["Compare with Backup" dired-backup-diff
|
||||
:help "Diff file at cursor with its latest backup"]
|
||||
["Compare Directories..." dired-compare-directories
|
||||
:help "Mark files with different attributes in two Dired buffers"]
|
||||
["Isearch in File Names..." dired-isearch-filenames
|
||||
:help "Incrementally search for string in file names only."]
|
||||
["Isearch Regexp in File Names..." dired-isearch-filenames-regexp
|
||||
:help "Incrementally search for regexp in file names only"]
|
||||
"---"
|
||||
["#Marked Files" dired-number-of-marked-files
|
||||
:help "Display the number and size of the marked files"]
|
||||
["Refresh" revert-buffer
|
||||
:help "Update contents of shown directories"]
|
||||
["Hide Details" dired-hide-details-mode
|
||||
:help "Hide details in buffer"
|
||||
:style toggle
|
||||
:selected dired-hide-details-mode]
|
||||
["Toggle Image Thumbnails in This Buffer" image-dired-dired-toggle-marked-thumbs
|
||||
:help "Add or remove image thumbnails in front of marked file names"]
|
||||
["Display Image" image-dired-dired-display-image
|
||||
:help "Display sized image in a separate window"]
|
||||
["Display Image Externally" image-dired-dired-display-external
|
||||
:help "Display image in external viewer"]))
|
||||
|
||||
(easy-menu-define dired-mode-regexp-menu dired-mode-map
|
||||
"Regexp menu for Dired mode."
|
||||
'("Regexp"
|
||||
["Mark Containing..." dired-mark-files-containing-regexp
|
||||
:help "Mark files whose contents matches regexp"]
|
||||
["Mark..." dired-mark-files-regexp
|
||||
:help "Mark files matching regexp for future operations"]
|
||||
["Flag..." dired-flag-files-regexp
|
||||
:help "Flag files matching regexp for deletion"]
|
||||
["Copy..." dired-do-copy-regexp
|
||||
:help "Copy marked files matching regexp"]
|
||||
["Rename..." dired-do-rename-regexp
|
||||
:help "Rename marked files matching regexp"]
|
||||
["Symlink..." dired-do-symlink-regexp
|
||||
:visible (fboundp 'make-symbolic-link)
|
||||
:help "Make symbolic links for files matching regexp"]
|
||||
["Hardlink..." dired-do-hardlink-regexp
|
||||
:help "Make hard links for files matching regexp"]
|
||||
["Upcase" dired-upcase
|
||||
:enable (or (not (fboundp 'msdos-long-file-names))
|
||||
(msdos-long-file-names))
|
||||
:help "Rename marked files to upper-case name"]
|
||||
["Downcase" dired-downcase
|
||||
;; When running on plain MS-DOS, there's only one
|
||||
;; letter-case for file names.
|
||||
:enable (or (not (fboundp 'msdos-long-file-names))
|
||||
(msdos-long-file-names))
|
||||
:help "Rename marked files to lower-case name"]
|
||||
"---"
|
||||
["Mark From Image Tag..." image-dired-mark-tagged-files
|
||||
:help "Mark files whose image tags matches regexp"]))
|
||||
|
||||
(easy-menu-define dired-mode-mark-menu dired-mode-map
|
||||
"Mark menu for Dired mode."
|
||||
'("Mark"
|
||||
["Toggle Marks" dired-toggle-marks
|
||||
:help "Mark unmarked files, unmark marked ones"]
|
||||
["Mark" dired-mark
|
||||
:help "Mark current line's file for future operations"]
|
||||
["Unmark" dired-unmark
|
||||
:help "Unmark or unflag current line's file"]
|
||||
["Flag" dired-flag-file-deletion
|
||||
:help "Flag current line's file for deletion"]
|
||||
["Flag Auto-save Files" dired-flag-auto-save-files
|
||||
:help "Flag auto-save files for deletion"]
|
||||
["Flag Backup Files" dired-flag-backup-files
|
||||
:help "Flag all backup files for deletion"]
|
||||
["Flag Garbage Files" dired-flag-garbage-files
|
||||
:help "Flag unneeded files for deletion"]
|
||||
["Mark Executables" dired-mark-executables
|
||||
:help "Mark all executable files"]
|
||||
["Mark Old Backups" dired-clean-directory
|
||||
:help "Flag old numbered backups for deletion"]
|
||||
["Mark Directories" dired-mark-directories
|
||||
:help "Mark all directories except `.' and `..'"]
|
||||
["Mark Symlinks" dired-mark-symlinks
|
||||
:visible (fboundp 'make-symbolic-link)
|
||||
:help "Mark all symbolic links"]
|
||||
["Unmark All" dired-unmark-all-marks]
|
||||
["Change Marks..." dired-change-marks
|
||||
:help "Replace marker with another character"]
|
||||
["Next Marked" dired-next-marked-file
|
||||
:help "Move to next marked file"]
|
||||
["Previous Marked" dired-prev-marked-file
|
||||
:help "Move to previous marked file"]))
|
||||
|
||||
(easy-menu-define dired-mode-operate-menu dired-mode-map
|
||||
"Operate menu for Dired mode."
|
||||
'("Operate"
|
||||
["Copy to..." dired-do-copy
|
||||
:help "Copy current file or all marked files"]
|
||||
["Rename to..." dired-do-rename
|
||||
:help "Rename current file or move marked files"]
|
||||
("Delete"
|
||||
["Delete Flagged Files" dired-do-flagged-delete
|
||||
:help "Delete all files flagged for deletion (D)"]
|
||||
["Delete Marked (Not Flagged) Files" dired-do-delete
|
||||
:help "Delete current file or all marked files (excluding flagged files)"])
|
||||
["Shell Command..." dired-do-shell-command
|
||||
:help "Run a shell command on current or marked files"]
|
||||
["Asynchronous Shell Command..." dired-do-async-shell-command
|
||||
:help "Run a shell command asynchronously on current or marked files"]
|
||||
["Symlink to..." dired-do-symlink
|
||||
:visible (fboundp 'make-symbolic-link)
|
||||
:help "Make symbolic links for current or marked files"]
|
||||
["Hardlink to..." dired-do-hardlink
|
||||
:help "Make hard links for current or marked files"]
|
||||
["Print..." dired-do-print
|
||||
:help "Ask for print command and print marked files"]
|
||||
["Compress" dired-do-compress
|
||||
:help "Compress/uncompress marked files"]
|
||||
["Byte-compile" dired-do-byte-compile
|
||||
:help "Byte-compile marked Emacs Lisp files"]
|
||||
["Load" dired-do-load
|
||||
:help "Load marked Emacs Lisp files"]
|
||||
["Change Timestamp..." dired-do-touch
|
||||
:help "Change timestamp of marked files"]
|
||||
["Change Mode..." dired-do-chmod
|
||||
:help "Change mode (attributes) of marked files"]
|
||||
["Change Group..." dired-do-chgrp
|
||||
:visible (not (memq system-type '(ms-dos windows-nt)))
|
||||
:help "Change the group of marked files"]
|
||||
["Change Owner..." dired-do-chown
|
||||
:visible (not (memq system-type '(ms-dos windows-nt)))
|
||||
:help "Change the owner of marked files"]
|
||||
["Isearch Files..." dired-do-isearch
|
||||
:help "Incrementally search marked files for string"]
|
||||
["Isearch Regexp Files..." dired-do-isearch-regexp
|
||||
:help "Incrementally search marked files for regexp"]
|
||||
["Search Files..." dired-do-find-regexp
|
||||
:help "Search marked files for matches of regexp"]
|
||||
["Query Replace in Files..." dired-do-find-regexp-and-replace
|
||||
:help "Replace regexp matches in marked files"]
|
||||
"---"
|
||||
["Encrypt..." epa-dired-do-encrypt
|
||||
:help "Encrypt current or marked files"]
|
||||
["Sign..." epa-dired-do-sign
|
||||
:help "Create digital signature of current or marked files"]
|
||||
["Verify" epa-dired-do-verify
|
||||
:help "Verify digital signature of current or marked files"]
|
||||
["Decrypt..." epa-dired-do-decrypt
|
||||
:help "Decrypt current or marked files"]
|
||||
"---"
|
||||
["Display Image Thumbnails" image-dired-display-thumbs
|
||||
:help "Display image thumbnails for current or marked image files"]
|
||||
["Add Image Comment..." image-dired-dired-comment-files
|
||||
:help "Add image comment to current or marked files"]
|
||||
["Add Image Tags..." image-dired-tag-files
|
||||
:help "Add image tags to current or marked files"]
|
||||
["Delete Image Tag..." image-dired-delete-tag
|
||||
:help "Delete image tag from current or marked files"]))
|
||||
|
||||
|
||||
;; Dired mode is suitable only for specially formatted data.
|
||||
(put 'dired-mode 'mode-class 'special)
|
||||
|
|
@ -4240,7 +4129,8 @@ Possible values:
|
|||
* `as-is': Show full switches.
|
||||
* Integer: Show only the first N chars of full switches.
|
||||
* Function: Pass `dired-actual-switches' as arg and show result."
|
||||
:group 'Dired-Plus
|
||||
:group 'dired
|
||||
:version "28.1"
|
||||
:type '(choice
|
||||
(const :tag "Indicate by name or date, else full" nil)
|
||||
(const :tag "Show full switches" as-is)
|
||||
|
|
|
|||
|
|
@ -62,39 +62,40 @@
|
|||
;; struct data item[/* items */];
|
||||
;; };
|
||||
;;
|
||||
;; The corresponding Lisp bindat specification looks like this:
|
||||
;; The corresponding Lisp bindat specification could look like this:
|
||||
;;
|
||||
;; (bindat-defmacro ip () '(vec 4 byte))
|
||||
;;
|
||||
;; (setq header-bindat-spec
|
||||
;; (bindat-spec
|
||||
;; (bindat-type
|
||||
;; (dest-ip ip)
|
||||
;; (src-ip ip)
|
||||
;; (dest-port u16)
|
||||
;; (src-port u16)))
|
||||
;; (dest-port uint 16)
|
||||
;; (src-port uint 16)))
|
||||
;;
|
||||
;; (setq data-bindat-spec
|
||||
;; (bindat-spec
|
||||
;; (bindat-type
|
||||
;; (type u8)
|
||||
;; (opcode u8)
|
||||
;; (length u32r) ;; little endian order
|
||||
;; (length uintr 32) ;; little endian order
|
||||
;; (id strz 8)
|
||||
;; (data vec (length))
|
||||
;; (align 4)))
|
||||
;; (data vec length)
|
||||
;; (_ align 4)))
|
||||
;;
|
||||
;; (setq packet-bindat-spec
|
||||
;; (bindat-spec
|
||||
;; (header struct header-bindat-spec)
|
||||
;; (items u8)
|
||||
;; (fill 3)
|
||||
;; (item repeat (items)
|
||||
;; (struct data-bindat-spec))))
|
||||
;;
|
||||
;; (bindat-type
|
||||
;; (header type header-bindat-spec)
|
||||
;; (nitems u8)
|
||||
;; (_ fill 3)
|
||||
;; (items repeat nitems type data-bindat-spec)))
|
||||
;;
|
||||
;; A binary data representation may look like
|
||||
;; [ 192 168 1 100 192 168 1 101 01 28 21 32 2 0 0 0
|
||||
;; 2 3 5 0 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0
|
||||
;; 1 4 7 0 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ]
|
||||
;;
|
||||
;; The corresponding decoded structure looks like
|
||||
;; The corresponding decoded structure returned by `bindat-unpack' (or taken
|
||||
;; by `bindat-pack') looks like:
|
||||
;;
|
||||
;; ((header
|
||||
;; (dest-ip . [192 168 1 100])
|
||||
|
|
@ -114,94 +115,28 @@
|
|||
;; (type . 1))))
|
||||
;;
|
||||
;; To access a specific value in this structure, use the function
|
||||
;; bindat-get-field with the structure as first arg followed by a list
|
||||
;; `bindat-get-field' with the structure as first arg followed by a list
|
||||
;; of field names and array indexes, e.g. using the data above,
|
||||
;; (bindat-get-field decoded-structure 'item 1 'id)
|
||||
;; returns "BCDEFG".
|
||||
|
||||
;; Binary Data Structure Specification Format
|
||||
;; ------------------------------------------
|
||||
|
||||
;; We recommend using names that end in `-bindat-spec'; such names
|
||||
;; are recognized automatically as "risky" variables.
|
||||
|
||||
;; The data specification is formatted as follows:
|
||||
|
||||
;; SPEC ::= ( ITEM... )
|
||||
|
||||
;; ITEM ::= ( FIELD TYPE )
|
||||
;; | ( [FIELD] eval FORM ) -- eval FORM for side-effect only
|
||||
;; | ( [FIELD] fill LEN ) -- skip LEN bytes
|
||||
;; | ( [FIELD] align LEN ) -- skip to next multiple of LEN bytes
|
||||
;; | ( [FIELD] struct SPEC_NAME )
|
||||
;; | ( [FIELD] union TAG_VAL (TAG SPEC)... [(t SPEC)] )
|
||||
;; | ( FIELD repeat ARG ITEM... )
|
||||
|
||||
;; -- In (eval EXPR), the value of the last field is available in
|
||||
;; the dynamically bound variable `last' and all the previous
|
||||
;; ones in the variable `struct'.
|
||||
|
||||
;; TYPE ::= ( eval EXPR ) -- interpret result as TYPE
|
||||
;; | u8 | byte -- length 1
|
||||
;; | u16 | word | short -- length 2, network byte order
|
||||
;; | u24 -- 3-byte value
|
||||
;; | u32 | dword | long -- length 4, network byte order
|
||||
;; | u64 -- length 8, network byte order
|
||||
;; | u16r | u24r | u32r | u64r - little endian byte order.
|
||||
;; | str LEN -- LEN byte string
|
||||
;; | strz LEN -- LEN byte (zero-terminated) string
|
||||
;; | vec LEN [TYPE] -- vector of LEN items of TYPE (default: u8)
|
||||
;; | ip -- 4 byte vector
|
||||
;; | bits LEN -- bit vector using LEN bytes.
|
||||
;;
|
||||
;; -- Example: `bits 2' will unpack 0x28 0x1c to (2 3 4 11 13)
|
||||
;; and 0x1c 0x28 to (3 5 10 11 12).
|
||||
|
||||
;; FIELD ::= ( eval EXPR ) -- use result as NAME
|
||||
;; | NAME
|
||||
|
||||
;; LEN ::= ARG
|
||||
;; | <omitted> | nil -- LEN = 1
|
||||
|
||||
|
||||
;; TAG_VAL ::= ARG
|
||||
|
||||
;; TAG ::= LISP_CONSTANT
|
||||
;; | ( eval EXPR ) -- return non-nil if tag match;
|
||||
;; current TAG_VAL in `tag'.
|
||||
|
||||
;; ARG ::= ( eval EXPR ) -- interpret result as ARG
|
||||
;; | INTEGER_CONSTANT
|
||||
;; | DEREF
|
||||
|
||||
;; DEREF ::= ( [NAME | INTEGER]... ) -- Field NAME or Array index relative
|
||||
;; to current structure spec.
|
||||
;; -- see bindat-get-field
|
||||
|
||||
;; A `union' specification
|
||||
;; ([FIELD] union TAG_VAL (TAG SPEC) ... [(t SPEC)])
|
||||
;; is interpreted by evalling TAG_VAL and then comparing that to
|
||||
;; each TAG using equal; if a match is found, the corresponding SPEC
|
||||
;; is used.
|
||||
;; If TAG is a form (eval EXPR), EXPR is eval'ed with `tag' bound to the
|
||||
;; value of TAG_VAL; the corresponding SPEC is used if the result is non-nil.
|
||||
;; Finally, if TAG is t, the corresponding SPEC is used unconditionally.
|
||||
;;
|
||||
;; An `eval' specification
|
||||
;; ([FIELD] eval FORM)
|
||||
;; is interpreted by evalling FORM for its side effects only.
|
||||
;; If FIELD is specified, the value is bound to that field.
|
||||
;; The FORM may access and update `bindat-raw' and `bindat-idx' (see `bindat-unpack').
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; Helper functions for structure unpacking.
|
||||
;; Relies on dynamic binding of `bindat-raw' and `bindat-idx'.
|
||||
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
(eval-when-compile (require 'subr-x)) ;For `named-let'.
|
||||
|
||||
(cl-defstruct (bindat--type
|
||||
(:predicate nil)
|
||||
(:constructor bindat--make))
|
||||
le ue pe)
|
||||
|
||||
(defvar bindat-raw)
|
||||
(defvar bindat-idx)
|
||||
|
||||
(defun bindat--unpack-u8 ()
|
||||
(defsubst bindat--unpack-u8 ()
|
||||
(prog1
|
||||
(aref bindat-raw bindat-idx)
|
||||
(setq bindat-idx (1+ bindat-idx))))
|
||||
|
|
@ -215,9 +150,6 @@
|
|||
(defun bindat--unpack-u32 ()
|
||||
(logior (ash (bindat--unpack-u16) 16) (bindat--unpack-u16)))
|
||||
|
||||
(defun bindat--unpack-u64 ()
|
||||
(logior (ash (bindat--unpack-u32) 32) (bindat--unpack-u32)))
|
||||
|
||||
(defun bindat--unpack-u16r ()
|
||||
(logior (bindat--unpack-u8) (ash (bindat--unpack-u8) 8)))
|
||||
|
||||
|
|
@ -227,50 +159,48 @@
|
|||
(defun bindat--unpack-u32r ()
|
||||
(logior (bindat--unpack-u16r) (ash (bindat--unpack-u16r) 16)))
|
||||
|
||||
(defun bindat--unpack-u64r ()
|
||||
(logior (bindat--unpack-u32r) (ash (bindat--unpack-u32r) 32)))
|
||||
(defun bindat--unpack-str (len)
|
||||
(let ((s (substring bindat-raw bindat-idx (+ bindat-idx len))))
|
||||
(setq bindat-idx (+ bindat-idx len))
|
||||
(if (stringp s) s
|
||||
(apply #'unibyte-string s))))
|
||||
|
||||
(defun bindat--unpack-strz (len)
|
||||
(let ((i 0) s)
|
||||
(while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
|
||||
(setq i (1+ i)))
|
||||
(setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
|
||||
(setq bindat-idx (+ bindat-idx len))
|
||||
(if (stringp s) s
|
||||
(apply #'unibyte-string s))))
|
||||
|
||||
(defun bindat--unpack-bits (len)
|
||||
(let ((bits nil) (bnum (1- (* 8 len))) j m)
|
||||
(while (>= bnum 0)
|
||||
(if (= (setq m (bindat--unpack-u8)) 0)
|
||||
(setq bnum (- bnum 8))
|
||||
(setq j 128)
|
||||
(while (> j 0)
|
||||
(if (/= 0 (logand m j))
|
||||
(setq bits (cons bnum bits)))
|
||||
(setq bnum (1- bnum)
|
||||
j (ash j -1)))))
|
||||
bits))
|
||||
|
||||
(defun bindat--unpack-item (type len &optional vectype)
|
||||
(if (eq type 'ip)
|
||||
(setq type 'vec len 4))
|
||||
(pcase type
|
||||
((or 'u8 'byte)
|
||||
(bindat--unpack-u8))
|
||||
((or 'u16 'word 'short)
|
||||
(bindat--unpack-u16))
|
||||
((or 'u8 'byte) (bindat--unpack-u8))
|
||||
((or 'u16 'word 'short) (bindat--unpack-u16))
|
||||
('u24 (bindat--unpack-u24))
|
||||
((or 'u32 'dword 'long)
|
||||
(bindat--unpack-u32))
|
||||
('u64 (bindat--unpack-u64))
|
||||
((or 'u32 'dword 'long) (bindat--unpack-u32))
|
||||
('u16r (bindat--unpack-u16r))
|
||||
('u24r (bindat--unpack-u24r))
|
||||
('u32r (bindat--unpack-u32r))
|
||||
('u64r (bindat--unpack-u64r))
|
||||
('bits
|
||||
(let ((bits nil) (bnum (1- (* 8 len))) j m)
|
||||
(while (>= bnum 0)
|
||||
(if (= (setq m (bindat--unpack-u8)) 0)
|
||||
(setq bnum (- bnum 8))
|
||||
(setq j 128)
|
||||
(while (> j 0)
|
||||
(if (/= 0 (logand m j))
|
||||
(setq bits (cons bnum bits)))
|
||||
(setq bnum (1- bnum)
|
||||
j (ash j -1)))))
|
||||
bits))
|
||||
('str
|
||||
(let ((s (substring bindat-raw bindat-idx (+ bindat-idx len))))
|
||||
(setq bindat-idx (+ bindat-idx len))
|
||||
(if (stringp s) s
|
||||
(apply #'unibyte-string s))))
|
||||
('strz
|
||||
(let ((i 0) s)
|
||||
(while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
|
||||
(setq i (1+ i)))
|
||||
(setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
|
||||
(setq bindat-idx (+ bindat-idx len))
|
||||
(if (stringp s) s
|
||||
(apply #'unibyte-string s))))
|
||||
('bits (bindat--unpack-bits len))
|
||||
('str (bindat--unpack-str len))
|
||||
('strz (bindat--unpack-strz len))
|
||||
('vec
|
||||
(let ((v (make-vector len 0)) (vlen 1))
|
||||
(if (consp vectype)
|
||||
|
|
@ -283,7 +213,15 @@
|
|||
v))
|
||||
(_ nil)))
|
||||
|
||||
(defsubst bindat--align (n len)
|
||||
(* len (/ (+ n (1- len)) len))) ;Isn't there a simpler way?
|
||||
|
||||
(defun bindat--unpack-group (spec)
|
||||
;; FIXME: Introduce a new primitive so we can mark `bindat-unpack'
|
||||
;; as obsolete (maybe that primitive should be a macro which takes
|
||||
;; a bindat type *expression* as argument).
|
||||
(if (cl-typep spec 'bindat--type)
|
||||
(funcall (bindat--type-ue spec))
|
||||
(with-suppressed-warnings ((lexical struct last))
|
||||
(defvar struct) (defvar last))
|
||||
(let (struct last)
|
||||
|
|
@ -317,8 +255,7 @@
|
|||
('fill
|
||||
(setq bindat-idx (+ bindat-idx len)))
|
||||
('align
|
||||
(while (/= (% bindat-idx len) 0)
|
||||
(setq bindat-idx (1+ bindat-idx))))
|
||||
(setq bindat-idx (bindat--align bindat-idx len)))
|
||||
('struct
|
||||
(setq data (bindat--unpack-group (eval len t))))
|
||||
('repeat
|
||||
|
|
@ -345,7 +282,7 @@
|
|||
(setq struct (if field
|
||||
(cons (cons field data) struct)
|
||||
(append data struct))))))
|
||||
struct))
|
||||
struct)))
|
||||
|
||||
(defun bindat-unpack (spec raw &optional idx)
|
||||
"Return structured data according to SPEC for binary data in RAW.
|
||||
|
|
@ -366,9 +303,8 @@ An integer value in the field list is taken as an array index,
|
|||
e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
||||
(while (and struct field)
|
||||
(setq struct (if (integerp (car field))
|
||||
(nth (car field) struct)
|
||||
(let ((val (assq (car field) struct)))
|
||||
(if (consp val) (cdr val)))))
|
||||
(elt struct (car field))
|
||||
(cdr (assq (car field) struct))))
|
||||
(setq field (cdr field)))
|
||||
struct)
|
||||
|
||||
|
|
@ -379,10 +315,11 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
(u16 . 2) (u16r . 2) (word . 2) (short . 2)
|
||||
(u24 . 3) (u24r . 3)
|
||||
(u32 . 4) (u32r . 4) (dword . 4) (long . 4)
|
||||
(u64 . 8) (u64r . 8)
|
||||
(ip . 4)))
|
||||
|
||||
(defun bindat--length-group (struct spec)
|
||||
(if (cl-typep spec 'bindat--type)
|
||||
(funcall (bindat--type-le spec) struct)
|
||||
(with-suppressed-warnings ((lexical struct last))
|
||||
(defvar struct) (defvar last))
|
||||
(let ((struct struct) last)
|
||||
|
|
@ -421,8 +358,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
('fill
|
||||
(setq bindat-idx (+ bindat-idx len)))
|
||||
('align
|
||||
(while (/= (% bindat-idx len) 0)
|
||||
(setq bindat-idx (1+ bindat-idx))))
|
||||
(setq bindat-idx (bindat--align bindat-idx len)))
|
||||
('struct
|
||||
(bindat--length-group
|
||||
(if field (bindat-get-field struct field) struct) (eval len t)))
|
||||
|
|
@ -449,7 +385,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
(setq len (* len (cdr type))))
|
||||
(if field
|
||||
(setq last (bindat-get-field struct field)))
|
||||
(setq bindat-idx (+ bindat-idx len))))))))
|
||||
(setq bindat-idx (+ bindat-idx len)))))))))
|
||||
|
||||
(defun bindat-length (spec struct)
|
||||
"Calculate `bindat-raw' length for STRUCT according to bindat SPEC."
|
||||
|
|
@ -460,7 +396,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
|
||||
;;;; Pack structured data into bindat-raw
|
||||
|
||||
(defun bindat--pack-u8 (v)
|
||||
(defsubst bindat--pack-u8 (v)
|
||||
(aset bindat-raw bindat-idx (logand v 255))
|
||||
(setq bindat-idx (1+ bindat-idx)))
|
||||
|
||||
|
|
@ -498,42 +434,39 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
(bindat--pack-u32r v)
|
||||
(bindat--pack-u32r (ash v -32)))
|
||||
|
||||
(defun bindat--pack-str (len v)
|
||||
(dotimes (i (min len (length v)))
|
||||
(aset bindat-raw (+ bindat-idx i) (aref v i)))
|
||||
(setq bindat-idx (+ bindat-idx len)))
|
||||
|
||||
(defun bindat--pack-bits (len v)
|
||||
(let ((bnum (1- (* 8 len))) j m)
|
||||
(while (>= bnum 0)
|
||||
(setq m 0)
|
||||
(if (null v)
|
||||
(setq bnum (- bnum 8))
|
||||
(setq j 128)
|
||||
(while (> j 0)
|
||||
(if (memq bnum v)
|
||||
(setq m (logior m j)))
|
||||
(setq bnum (1- bnum)
|
||||
j (ash j -1))))
|
||||
(bindat--pack-u8 m))))
|
||||
|
||||
(defun bindat--pack-item (v type len &optional vectype)
|
||||
(if (eq type 'ip)
|
||||
(setq type 'vec len 4))
|
||||
(pcase type
|
||||
((guard (null v))
|
||||
(setq bindat-idx (+ bindat-idx len)))
|
||||
((or 'u8 'byte)
|
||||
(bindat--pack-u8 v))
|
||||
((or 'u16 'word 'short)
|
||||
(bindat--pack-u16 v))
|
||||
('u24
|
||||
(bindat--pack-u24 v))
|
||||
((or 'u32 'dword 'long)
|
||||
(bindat--pack-u32 v))
|
||||
('u64 (bindat--pack-u64 v))
|
||||
((guard (null v)) (setq bindat-idx (+ bindat-idx len)))
|
||||
((or 'u8 'byte) (bindat--pack-u8 v))
|
||||
((or 'u16 'word 'short) (bindat--pack-u16 v))
|
||||
('u24 (bindat--pack-u24 v))
|
||||
((or 'u32 'dword 'long) (bindat--pack-u32 v))
|
||||
('u16r (bindat--pack-u16r v))
|
||||
('u24r (bindat--pack-u24r v))
|
||||
('u32r (bindat--pack-u32r v))
|
||||
('u64r (bindat--pack-u64r v))
|
||||
('bits
|
||||
(let ((bnum (1- (* 8 len))) j m)
|
||||
(while (>= bnum 0)
|
||||
(setq m 0)
|
||||
(if (null v)
|
||||
(setq bnum (- bnum 8))
|
||||
(setq j 128)
|
||||
(while (> j 0)
|
||||
(if (memq bnum v)
|
||||
(setq m (logior m j)))
|
||||
(setq bnum (1- bnum)
|
||||
j (ash j -1))))
|
||||
(bindat--pack-u8 m))))
|
||||
((or 'str 'strz)
|
||||
(dotimes (i (min len (length v)))
|
||||
(aset bindat-raw (+ bindat-idx i) (aref v i)))
|
||||
(setq bindat-idx (+ bindat-idx len)))
|
||||
('bits (bindat--pack-bits len v))
|
||||
((or 'str 'strz) (bindat--pack-str len v))
|
||||
('vec
|
||||
(let ((l (length v)) (vlen 1))
|
||||
(if (consp vectype)
|
||||
|
|
@ -548,6 +481,8 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
(setq bindat-idx (+ bindat-idx len)))))
|
||||
|
||||
(defun bindat--pack-group (struct spec)
|
||||
(if (cl-typep spec 'bindat--type)
|
||||
(funcall (bindat--type-pe spec) struct)
|
||||
(with-suppressed-warnings ((lexical struct last))
|
||||
(defvar struct) (defvar last))
|
||||
(let ((struct struct) last)
|
||||
|
|
@ -580,8 +515,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
('fill
|
||||
(setq bindat-idx (+ bindat-idx len)))
|
||||
('align
|
||||
(while (/= (% bindat-idx len) 0)
|
||||
(setq bindat-idx (1+ bindat-idx))))
|
||||
(setq bindat-idx (bindat--align bindat-idx len)))
|
||||
('struct
|
||||
(bindat--pack-group
|
||||
(if field (bindat-get-field struct field) struct) (eval len t)))
|
||||
|
|
@ -606,7 +540,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
|
|||
(_
|
||||
(setq last (bindat-get-field struct field))
|
||||
(bindat--pack-item last type len vectype)
|
||||
))))))
|
||||
)))))))
|
||||
|
||||
(defun bindat-pack (spec struct &optional raw idx)
|
||||
"Return binary data packed according to SPEC for structured data STRUCT.
|
||||
|
|
@ -622,52 +556,6 @@ Optional fourth arg IDX is the starting offset into RAW."
|
|||
(bindat--pack-group struct spec)
|
||||
(if raw nil bindat-raw)))
|
||||
|
||||
;;;; Debugging support
|
||||
|
||||
(def-edebug-elem-spec 'bindat-spec '(&rest bindat-item))
|
||||
|
||||
|
||||
(def-edebug-elem-spec 'bindat--item-aux
|
||||
;; Field types which can come without a field label.
|
||||
'(&or ["eval" form]
|
||||
["fill" bindat-len]
|
||||
["align" bindat-len]
|
||||
["struct" form] ;A reference to another bindat-spec.
|
||||
["union" bindat-tag-val &rest (bindat-tag bindat-spec)]))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-item
|
||||
'((&or bindat--item-aux ;Without label..
|
||||
[bindat-field ;..or with label
|
||||
&or bindat--item-aux
|
||||
["repeat" bindat-arg bindat-spec]
|
||||
bindat-type])))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-type
|
||||
'(&or ("eval" form)
|
||||
["str" bindat-len]
|
||||
["strz" bindat-len]
|
||||
["vec" bindat-len &optional bindat-type]
|
||||
["bits" bindat-len]
|
||||
symbolp))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-field
|
||||
'(&or ("eval" form) symbolp))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-len '(&or [] "nil" bindat-arg))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-tag-val '(bindat-arg))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-tag '(&or ("eval" form) atom))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-arg
|
||||
'(&or ("eval" form) integerp (&rest symbolp integerp)))
|
||||
|
||||
(defmacro bindat-spec (&rest fields)
|
||||
"Build the bindat spec described by FIELDS."
|
||||
(declare (indent 0) (debug (bindat-spec)))
|
||||
;; FIXME: We should really "compile" this to a triplet of functions!
|
||||
`',fields)
|
||||
|
||||
;;;; Misc. format conversions
|
||||
|
||||
(defun bindat-format-vector (vect fmt sep &optional len)
|
||||
|
|
@ -696,6 +584,384 @@ The port (if any) is omitted. IP can be a string, as well."
|
|||
(format "%d.%d.%d.%d"
|
||||
(aref ip 0) (aref ip 1) (aref ip 2) (aref ip 3))))
|
||||
|
||||
;;;; New approach based on macro-expansion
|
||||
|
||||
;; Further improvements suggested by reading websocket.el:
|
||||
;; - Support for bit-sized fields?
|
||||
;;
|
||||
;; - Add some way to verify redundant/checksum fields's contents without
|
||||
;; having to provide a complete `:unpack-val' expression.
|
||||
;; The `:pack-val' thingy can work nicely to compute checksum fields
|
||||
;; based on previous fields's contents (without impacting or being impacted
|
||||
;; by the unpacked representation), but if we want to verify
|
||||
;; those checksums when unpacking, we have to use the :unpack-val
|
||||
;; and build the whole object by hand instead of being able to focus
|
||||
;; just on the checksum field.
|
||||
;; Maybe this could be related to `unit' type fields where we might like
|
||||
;; to make sure that the "value" we write into it is the same as the
|
||||
;; value it holds (tho those checks don't happen at the same time (pack
|
||||
;; vs unpack).
|
||||
;;
|
||||
;; - Support for packing/unpacking to/from something else than
|
||||
;; a unibyte string, e.g. from a buffer. Problems to do that are:
|
||||
;; - the `str' and `strz' types which use `substring' rather than reading
|
||||
;; one byte at a time.
|
||||
;; - the `align' and `fill' which just want to skip without reading/writing
|
||||
;; - the `pack-uint' case, which would prefer writing the LSB first.
|
||||
;; - the `align' case needs to now the current position in order to know
|
||||
;; how far to advance
|
||||
;;
|
||||
;; - Don't write triple code when the type is only ever used at a single place
|
||||
;; (e.g. to unpack).
|
||||
|
||||
(defun bindat--unpack-uint (bitlen)
|
||||
(let ((v 0) (bitsdone 0))
|
||||
(while (< bitsdone bitlen)
|
||||
(setq v (logior (ash v 8) (bindat--unpack-u8)))
|
||||
(setq bitsdone (+ bitsdone 8)))
|
||||
v))
|
||||
|
||||
(defun bindat--unpack-uintr (bitlen)
|
||||
(let ((v 0) (bitsdone 0))
|
||||
(while (< bitsdone bitlen)
|
||||
(setq v (logior v (ash (bindat--unpack-u8) bitsdone)))
|
||||
(setq bitsdone (+ bitsdone 8)))
|
||||
v))
|
||||
|
||||
(defun bindat--pack-uint (bitlen v)
|
||||
(let* ((len (/ bitlen 8))
|
||||
(shift (- (* 8 (1- len)))))
|
||||
(dotimes (_ len)
|
||||
(bindat--pack-u8 (logand 255 (ash v shift)))
|
||||
(setq shift (+ 8 shift)))))
|
||||
|
||||
(defun bindat--pack-uintr (bitlen v)
|
||||
(let* ((len (/ bitlen 8)))
|
||||
(dotimes (_ len)
|
||||
(bindat--pack-u8 (logand v 255))
|
||||
(setq v (ash v -8)))))
|
||||
|
||||
(defmacro bindat--pcase (&rest args)
|
||||
"Like `pcase' but optimize the code under the assumption that it's exhaustive."
|
||||
(declare (indent 1) (debug pcase))
|
||||
`(pcase ,@args (pcase--dontcare nil)))
|
||||
|
||||
(cl-defgeneric bindat--type (op head &rest args)
|
||||
"Return the code for the operation OP of the Bindat type (HEAD . ARGS).
|
||||
OP can be one of: unpack', (pack VAL), or (length VAL) where VAL
|
||||
is the name of a variable that will hold the value we need to pack.")
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql byte)))
|
||||
(bindat--pcase op
|
||||
('unpack `(bindat--unpack-u8))
|
||||
(`(length . ,_) `(cl-incf bindat-idx 1))
|
||||
(`(pack . ,args) `(bindat--pack-u8 . ,args))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql uint)) n)
|
||||
(if (eq n 8) (bindat--type op 'byte)
|
||||
(bindat--pcase op
|
||||
('unpack `(bindat--unpack-uint ,n))
|
||||
(`(length . ,_) `(cl-incf bindat-idx (/ ,n 8)))
|
||||
(`(pack . ,args) `(bindat--pack-uint ,n . ,args)))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql uintr)) n)
|
||||
(if (eq n 8) (bindat--type op 'byte)
|
||||
(bindat--pcase op
|
||||
('unpack `(bindat--unpack-uintr ,n))
|
||||
(`(length . ,_) `(cl-incf bindat-idx (/ ,n 8)))
|
||||
(`(pack . ,args) `(bindat--pack-uintr ,n . ,args)))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql str)) len)
|
||||
(bindat--pcase op
|
||||
('unpack `(bindat--unpack-str ,len))
|
||||
(`(length . ,_) `(cl-incf bindat-idx ,len))
|
||||
(`(pack . ,args) `(bindat--pack-str ,len . ,args))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql strz)) len)
|
||||
(bindat--pcase op
|
||||
('unpack `(bindat--unpack-strz ,len))
|
||||
(`(length . ,_) `(cl-incf bindat-idx ,len))
|
||||
;; Here we don't add the terminating zero because we rely
|
||||
;; on the fact that `bindat-raw' was presumably initialized with
|
||||
;; all-zeroes before we started.
|
||||
(`(pack . ,args) `(bindat--pack-str ,len . ,args))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql bits)) len)
|
||||
(bindat--pcase op
|
||||
('unpack `(bindat--unpack-bits ,len))
|
||||
(`(length . ,_) `(cl-incf bindat-idx ,len))
|
||||
(`(pack . ,args) `(bindat--pack-bits ,len . ,args))))
|
||||
|
||||
(cl-defmethod bindat--type (_op (_ (eql fill)) len)
|
||||
`(progn (cl-incf bindat-idx ,len) nil))
|
||||
|
||||
(cl-defmethod bindat--type (_op (_ (eql align)) len)
|
||||
`(progn (cl-callf bindat--align bindat-idx ,len) nil))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql type)) exp)
|
||||
(bindat--pcase op
|
||||
('unpack `(funcall (bindat--type-ue ,exp)))
|
||||
(`(length . ,args) `(funcall (bindat--type-le ,exp) . ,args))
|
||||
(`(pack . ,args) `(funcall (bindat--type-pe ,exp) . ,args))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql vec)) count &rest type)
|
||||
(unless type (setq type '(byte)))
|
||||
(let ((fun (macroexpand-all (bindat--fun type) macroexpand-all-environment)))
|
||||
(bindat--pcase op
|
||||
('unpack
|
||||
`(let* ((bindat--len ,count)
|
||||
(bindat--v (make-vector bindat--len 0)))
|
||||
(dotimes (bindat--i bindat--len)
|
||||
(aset bindat--v bindat--i (funcall ,fun)))
|
||||
bindat--v))
|
||||
((and `(length . ,_)
|
||||
;; FIXME: Improve the pattern match to recognize more complex
|
||||
;; "constant" functions?
|
||||
(let `#'(lambda (,val) (setq bindat-idx (+ bindat-idx ,len))) fun)
|
||||
(guard (not (macroexp--fgrep `((,val)) len))))
|
||||
;; Optimize the case where the size of each element is constant.
|
||||
`(cl-incf bindat-idx (* ,count ,len)))
|
||||
;; FIXME: It's tempting to use `(mapc (lambda (,val) ,exp) ,val)'
|
||||
;; which would be more efficient when `val' is a list,
|
||||
;; but that's only right if length of `val' is indeed `count'.
|
||||
(`(,_ ,val)
|
||||
`(dotimes (bindat--i ,count)
|
||||
(funcall ,fun (elt ,val bindat--i)))))))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql unit)) val)
|
||||
(pcase op ('unpack val) (_ nil)))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql struct)) &rest args)
|
||||
(apply #'bindat--type op args))
|
||||
|
||||
(cl-defmethod bindat--type (op (_ (eql :pack-var)) var &rest fields)
|
||||
(unless (consp (cdr fields))
|
||||
(error "`:pack-var VAR' needs to be followed by fields"))
|
||||
(bindat--pcase op
|
||||
((or 'unpack (guard (null var)))
|
||||
(apply #'bindat--type op fields))
|
||||
(`(,_ ,val)
|
||||
`(let ((,var ,val)) ,(apply #'bindat--type op fields)))))
|
||||
|
||||
(cl-defmethod bindat--type (op (field cons) &rest fields)
|
||||
(named-let loop
|
||||
((fields (cons field fields))
|
||||
(labels ()))
|
||||
(bindat--pcase fields
|
||||
('nil
|
||||
(bindat--pcase op
|
||||
('unpack
|
||||
(let ((exp ()))
|
||||
(pcase-dolist (`(,label . ,labelvar) labels)
|
||||
(setq exp
|
||||
(if (eq label '_)
|
||||
(if exp `(nconc ,labelvar ,exp) labelvar)
|
||||
`(cons (cons ',label ,labelvar) ,exp))))
|
||||
exp))
|
||||
(_ nil)))
|
||||
(`(:unpack-val ,exp)
|
||||
;; Make it so `:kwd nil' is the same as the absence of the keyword arg.
|
||||
(if exp (pcase op ('unpack exp)) (loop nil labels)))
|
||||
|
||||
(`((,label . ,type) . ,fields)
|
||||
(let* ((get-field-val
|
||||
(let ((tail (memq :pack-val type)))
|
||||
;; FIXME: This `TYPE.. :pack EXP' syntax doesn't work well
|
||||
;; when TYPE is a struct (a list of fields) or with extensions
|
||||
;; such as allowing TYPE to be `if ...'.
|
||||
(if tail
|
||||
(prog1 (cadr tail)
|
||||
(setq type (butlast type (length tail)))))))
|
||||
(fieldvar (make-symbol (format "field%d" (length fields))))
|
||||
(labelvar
|
||||
(cond
|
||||
((eq label '_) fieldvar)
|
||||
((keywordp label)
|
||||
(intern (substring (symbol-name label) 1)))
|
||||
(t label)))
|
||||
(field-fun (bindat--fun type))
|
||||
(rest-exp (loop fields `((,label . ,labelvar) . ,labels))))
|
||||
(bindat--pcase op
|
||||
('unpack
|
||||
(let ((code
|
||||
`(let ((,labelvar (funcall ,field-fun)))
|
||||
,rest-exp)))
|
||||
(if (or (eq label '_) (not (assq label labels)))
|
||||
code
|
||||
(macroexp-warn-and-return
|
||||
(format "Duplicate label: %S" label)
|
||||
code))))
|
||||
(`(,_ ,val)
|
||||
;; `cdr-safe' is easier to optimize (can't signal an error).
|
||||
`(let ((,fieldvar ,(or get-field-val
|
||||
(if (eq label '_) val
|
||||
`(cdr-safe (assq ',label ,val))))))
|
||||
(funcall ,field-fun ,fieldvar)
|
||||
,@(when rest-exp
|
||||
`((let ,(unless (eq labelvar fieldvar)
|
||||
`((,labelvar ,fieldvar)))
|
||||
(ignore ,labelvar)
|
||||
,rest-exp))))))))
|
||||
(_ (error "Unrecognized format in bindat fields: %S" fields)))))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-struct
|
||||
'([&rest (symbolp bindat-type &optional ":pack-val" def-form)]
|
||||
&optional ":unpack-val" def-form))
|
||||
|
||||
(def-edebug-elem-spec 'bindat-type
|
||||
'(&or ["uint" def-form]
|
||||
["uintr" def-form]
|
||||
["str" def-form]
|
||||
["strz" def-form]
|
||||
["bits" def-form]
|
||||
["fill" def-form]
|
||||
["align" def-form]
|
||||
["vec" def-form bindat-type]
|
||||
["repeat" def-form bindat-type]
|
||||
["type" def-form]
|
||||
["struct" bindat-struct]
|
||||
["unit" def-form]
|
||||
[":pack-var" symbolp bindat-type]
|
||||
symbolp ;; u8, u16, etc...
|
||||
bindat-struct))
|
||||
|
||||
(defmacro bindat-type (&rest type)
|
||||
"Return the Bindat type value to pack&unpack TYPE.
|
||||
TYPE is a Bindat type expression. It can take the following forms:
|
||||
|
||||
uint BITLEN - Big-endian unsigned integer
|
||||
uintr BITLEN - Little-endian unsigned integer
|
||||
str LEN - Byte string
|
||||
strz LEN - Zero-terminated byte-string
|
||||
bits LEN - Bit vector (LEN is counted in bytes)
|
||||
fill LEN - Just a filler
|
||||
align LEN - Fill up to the next multiple of LEN bytes
|
||||
vec COUNT TYPE - COUNT repetitions of TYPE
|
||||
type EXP - Indirection; EXP should return a Bindat type value
|
||||
unit EXP - 0-width type holding the value returned by EXP
|
||||
struct FIELDS... - A composite type
|
||||
|
||||
When the context makes it clear, the symbol `struct' can be omitted.
|
||||
A composite type is a list of FIELDS where each FIELD is of the form
|
||||
|
||||
(LABEL TYPE)
|
||||
|
||||
where LABEL can be `_' if the field should not deserve a name.
|
||||
|
||||
Composite types get normally packed/unpacked to/from alists, but this can be
|
||||
controlled in the following way:
|
||||
- If the list of fields ends with `:unpack-val EXP', then unpacking will
|
||||
return the value of EXP (which has the previous fields in its scope).
|
||||
- If a field's TYPE is followed by `:pack-val EXP', then the value placed
|
||||
into this field will be that returned by EXP instead of looking up the alist.
|
||||
- If the list of fields is preceded with `:pack-var VAR' then the object to
|
||||
be packed is bound to VAR when evaluating the EXPs of `:pack-val'.
|
||||
|
||||
All the above BITLEN, LEN, COUNT, and EXP are ELisp expressions evaluated
|
||||
in the current lexical context extended with the previous fields.
|
||||
|
||||
TYPE can additionally be one of the Bindat type macros defined with
|
||||
`bindat-defmacro' (and listed below) or an ELisp expression which returns
|
||||
a bindat type expression."
|
||||
(declare (indent 0) (debug (bindat-type)))
|
||||
`(progn
|
||||
(defvar bindat-idx)
|
||||
(bindat--make :ue ,(bindat--toplevel 'unpack type)
|
||||
:le ,(bindat--toplevel 'length type)
|
||||
:pe ,(bindat--toplevel 'pack type))))
|
||||
|
||||
(eval-and-compile
|
||||
(defconst bindat--primitives '(byte uint uintr str strz bits fill align
|
||||
struct type vec unit)))
|
||||
|
||||
(eval-and-compile
|
||||
(defvar bindat--macroenv
|
||||
(mapcar (lambda (s) (cons s (lambda (&rest args)
|
||||
(bindat--makefun (cons s args)))))
|
||||
bindat--primitives)))
|
||||
|
||||
(defmacro bindat-defmacro (name args &rest body)
|
||||
"Define a new Bindat type as a macro."
|
||||
(declare (indent 2) (doc-string 3) (debug (&define name sexp def-body)))
|
||||
(let ((leaders ()))
|
||||
(while (and (cdr body)
|
||||
(or (stringp (car body))
|
||||
(memq (car-safe (car body)) '(:documentation declare))))
|
||||
(push (pop body) leaders))
|
||||
;; FIXME: Add support for Edebug decls to those macros.
|
||||
`(eval-and-compile ;; Yuck! But needed to define types where you use them!
|
||||
(setf (alist-get ',name bindat--macroenv)
|
||||
(lambda ,args ,@(nreverse leaders)
|
||||
(bindat--fun ,(macroexp-progn body)))))))
|
||||
|
||||
(put 'bindat-type 'function-documentation '(bindat--make-docstring))
|
||||
(defun bindat--make-docstring ()
|
||||
;; Largely inspired from `pcase--make-docstring'.
|
||||
(let* ((main (documentation (symbol-function 'bindat-type) 'raw))
|
||||
(ud (help-split-fundoc main 'bindat-type)))
|
||||
(require 'help-fns)
|
||||
(declare-function help-fns--signature "help-fns")
|
||||
(with-temp-buffer
|
||||
(insert (or (cdr ud) main))
|
||||
(pcase-dolist (`(,name . ,me) (reverse bindat--macroenv))
|
||||
(unless (memq name bindat--primitives)
|
||||
(let ((doc (documentation me 'raw)))
|
||||
(insert "\n\n-- ")
|
||||
(setq doc (help-fns--signature name doc me
|
||||
(indirect-function me)
|
||||
nil))
|
||||
(insert "\n" (or doc "Not documented.")))))
|
||||
(let ((combined-doc (buffer-string)))
|
||||
(if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))))
|
||||
|
||||
(bindat-defmacro u8 () "Unsigned 8bit integer." '(byte))
|
||||
(bindat-defmacro sint (bitlen r)
|
||||
"Signed integer of size BITLEN.
|
||||
Bigendian if R is nil and little endian if not."
|
||||
(let ((bl (make-symbol "bitlen"))
|
||||
(max (make-symbol "max"))
|
||||
(wrap (make-symbol "wrap")))
|
||||
`(let* ((,bl ,bitlen)
|
||||
(,max (ash 1 (1- ,bl)))
|
||||
(,wrap (+ ,max ,max)))
|
||||
(struct :pack-var v
|
||||
(n if ,r (uintr ,bl) (uint ,bl)
|
||||
:pack-val (if (< v 0) (+ v ,wrap) v))
|
||||
:unpack-val (if (>= n ,max) (- n ,wrap) n)))))
|
||||
|
||||
(bindat-defmacro repeat (count &rest type)
|
||||
"Like `vec', but unpacks to a list rather than a vector."
|
||||
`(:pack-var v
|
||||
(v vec ,count ,@type :pack-val v)
|
||||
:unpack-val (append v nil)))
|
||||
|
||||
(defvar bindat--op nil
|
||||
"The operation we're currently building.
|
||||
This is a simple symbol and can be one of: `unpack', `pack', or `length'.
|
||||
This is used during macroexpansion of `bindat-type' so that the
|
||||
macros know which code to generate.
|
||||
FIXME: this is closely related and very similar to the `op' argument passed
|
||||
to `bindat--type', yet it's annoyingly different.")
|
||||
|
||||
(defun bindat--fun (type)
|
||||
(if (or (keywordp (car type)) (consp (car type))) (cons 'struct type)
|
||||
type))
|
||||
|
||||
(defun bindat--makefun (type)
|
||||
(let* ((v (make-symbol "v"))
|
||||
(args (pcase bindat--op ('unpack ()) (_ (list v)))))
|
||||
(pcase (apply #'bindat--type
|
||||
(pcase bindat--op ('unpack 'unpack) (op `(,op . ,args)))
|
||||
type)
|
||||
(`(funcall ,f . ,(pred (equal args))) f) ;η-reduce.
|
||||
(exp `(lambda ,args ,exp)))))
|
||||
|
||||
(defun bindat--toplevel (op type)
|
||||
(let* ((bindat--op op)
|
||||
(env `(,@bindat--macroenv
|
||||
,@macroexpand-all-environment)))
|
||||
(macroexpand-all (bindat--fun type) env)))
|
||||
|
||||
(provide 'bindat)
|
||||
|
||||
;;; bindat.el ends here
|
||||
|
|
|
|||
|
|
@ -607,9 +607,12 @@ Same format as `byte-optimize--lexvars', with shared structure and contents.")
|
|||
(setq args (cddr args)))
|
||||
(cons fn (nreverse var-expr-list))))
|
||||
|
||||
(`(defvar ,(and (pred symbolp) name) . ,_)
|
||||
(push name byte-optimize--dynamic-vars)
|
||||
form)
|
||||
(`(defvar ,(and (pred symbolp) name) . ,rest)
|
||||
(let ((optimized-rest (and rest
|
||||
(cons (byte-optimize-form (car rest) nil)
|
||||
(cdr rest)))))
|
||||
(push name byte-optimize--dynamic-vars)
|
||||
`(defvar ,name . ,optimized-rest)))
|
||||
|
||||
(`(,(pred byte-code-function-p) . ,exps)
|
||||
(cons fn (mapcar #'byte-optimize-form exps)))
|
||||
|
|
@ -1413,7 +1416,8 @@ Same format as `byte-optimize--lexvars', with shared structure and contents.")
|
|||
copysign isnan ldexp float logb
|
||||
floor ceiling round truncate
|
||||
ffloor fceiling fround ftruncate
|
||||
string= string-equal string< string-lessp
|
||||
string= string-equal string< string-lessp string> string-greaterp
|
||||
string-empty-p string-blank-p string-prefix-p string-suffix-p
|
||||
string-search
|
||||
consp atom listp nlistp proper-list-p
|
||||
sequencep arrayp vectorp stringp bool-vector-p hash-table-p
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ The return value is undefined.
|
|||
#'(lambda (x)
|
||||
(let ((f (cdr (assq (car x) macro-declarations-alist))))
|
||||
(if f (apply (car f) name arglist (cdr x))
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format-message
|
||||
"Unknown macro property %S in %S"
|
||||
(car x) name)
|
||||
|
|
@ -326,7 +326,7 @@ The return value is undefined.
|
|||
body)))
|
||||
nil)
|
||||
(t
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format-message "Unknown defun property `%S' in %S"
|
||||
(car x) name)
|
||||
nil)))))
|
||||
|
|
|
|||
|
|
@ -2497,8 +2497,6 @@ list that represents a doc string reference.
|
|||
byte-compile-output nil
|
||||
byte-compile-jump-tables nil))))
|
||||
|
||||
(defvar byte-compile-force-lexical-warnings nil)
|
||||
|
||||
(defun byte-compile-preprocess (form &optional _for-effect)
|
||||
(setq form (macroexpand-all form byte-compile-macro-environment))
|
||||
;; FIXME: We should run byte-optimize-form here, but it currently does not
|
||||
|
|
@ -2509,7 +2507,6 @@ list that represents a doc string reference.
|
|||
;; (setq form (byte-optimize-form form for-effect)))
|
||||
(cond
|
||||
(lexical-binding (cconv-closure-convert form))
|
||||
(byte-compile-force-lexical-warnings (cconv-warnings-only form))
|
||||
(t form)))
|
||||
|
||||
;; byte-hunk-handlers cannot call this!
|
||||
|
|
@ -2872,16 +2869,12 @@ FUN should be either a `lambda' value or a `closure' value."
|
|||
(dolist (binding env)
|
||||
(cond
|
||||
((consp binding)
|
||||
;; We check shadowing by the args, so that the `let' can be moved
|
||||
;; within the lambda, which can then be unfolded. FIXME: Some of those
|
||||
;; bindings might be unused in `body'.
|
||||
(unless (memq (car binding) args) ;Shadowed.
|
||||
(push `(,(car binding) ',(cdr binding)) renv)))
|
||||
(push `(,(car binding) ',(cdr binding)) renv))
|
||||
((eq binding t))
|
||||
(t (push `(defvar ,binding) body))))
|
||||
(if (null renv)
|
||||
`(lambda ,args ,@preamble ,@body)
|
||||
`(lambda ,args ,@preamble (let ,(nreverse renv) ,@body)))))
|
||||
`(let ,renv (lambda ,args ,@preamble ,@body)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun byte-compile (form)
|
||||
|
|
@ -2906,23 +2899,27 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
|||
(if (symbolp form) form "provided"))
|
||||
fun)
|
||||
(t
|
||||
(when (or (symbolp form) (eq (car-safe fun) 'closure))
|
||||
;; `fun' is a function *value*, so try to recover its corresponding
|
||||
;; source code.
|
||||
(setq lexical-binding (eq (car fun) 'closure))
|
||||
(setq fun (byte-compile--reify-function fun)))
|
||||
;; Expand macros.
|
||||
(setq fun (byte-compile-preprocess fun))
|
||||
(setq fun (byte-compile-top-level fun nil 'eval))
|
||||
(if (symbolp form)
|
||||
;; byte-compile-top-level returns an *expression* equivalent to the
|
||||
;; `fun' expression, so we need to evaluate it, tho normally
|
||||
;; this is not needed because the expression is just a constant
|
||||
;; byte-code object, which is self-evaluating.
|
||||
(setq fun (eval fun t)))
|
||||
(if macro (push 'macro fun))
|
||||
(if (symbolp form) (fset form fun))
|
||||
fun))))))
|
||||
(let (final-eval)
|
||||
(when (or (symbolp form) (eq (car-safe fun) 'closure))
|
||||
;; `fun' is a function *value*, so try to recover its corresponding
|
||||
;; source code.
|
||||
(setq lexical-binding (eq (car fun) 'closure))
|
||||
(setq fun (byte-compile--reify-function fun))
|
||||
(setq final-eval t))
|
||||
;; Expand macros.
|
||||
(setq fun (byte-compile-preprocess fun))
|
||||
(setq fun (byte-compile-top-level fun nil 'eval))
|
||||
(if (symbolp form)
|
||||
;; byte-compile-top-level returns an *expression* equivalent to the
|
||||
;; `fun' expression, so we need to evaluate it, tho normally
|
||||
;; this is not needed because the expression is just a constant
|
||||
;; byte-code object, which is self-evaluating.
|
||||
(setq fun (eval fun t)))
|
||||
(if final-eval
|
||||
(setq fun (eval fun t)))
|
||||
(if macro (push 'macro fun))
|
||||
(if (symbolp form) (fset form fun))
|
||||
fun)))))))
|
||||
|
||||
(defun byte-compile-sexp (sexp)
|
||||
"Compile and return SEXP."
|
||||
|
|
@ -5319,8 +5316,9 @@ already up-to-date."
|
|||
"Reload any Lisp file that was changed since Emacs was dumped.
|
||||
Use with caution."
|
||||
(let* ((argv0 (car command-line-args))
|
||||
(emacs-file (executable-find argv0)))
|
||||
(if (not (and emacs-file (file-executable-p emacs-file)))
|
||||
(emacs-file (or (cdr (nth 2 (pdumper-stats)))
|
||||
(executable-find argv0))))
|
||||
(if (not (and emacs-file (file-exists-p emacs-file)))
|
||||
(message "Can't find %s to refresh preloaded Lisp files" argv0)
|
||||
(dolist (f (reverse load-history))
|
||||
(setq f (car f))
|
||||
|
|
|
|||
|
|
@ -121,19 +121,22 @@
|
|||
(defconst cconv-liftwhen 6
|
||||
"Try to do lambda lifting if the number of arguments + free variables
|
||||
is less than this number.")
|
||||
;; List of all the variables that are both captured by a closure
|
||||
;; and mutated. Each entry in the list takes the form
|
||||
;; (BINDER . PARENTFORM) where BINDER is the (VAR VAL) that introduces the
|
||||
;; variable (or is just (VAR) for variables not introduced by let).
|
||||
(defvar cconv-captured+mutated)
|
||||
(defvar cconv-var-classification
|
||||
;; Alist mapping variables to a given class.
|
||||
;; The keys are of the form (BINDER . PARENTFORM) where BINDER
|
||||
;; is the (VAR VAL) that introduces it (or is just (VAR) for variables
|
||||
;; not introduced by let).
|
||||
;; The class can be one of:
|
||||
;; - :unused
|
||||
;; - :lambda-candidate
|
||||
;; - :captured+mutated
|
||||
;; - nil for "normal" variables, which would then just not appear
|
||||
;; in the alist at all.
|
||||
)
|
||||
|
||||
;; List of candidates for lambda lifting.
|
||||
;; Each candidate has the form (BINDER . PARENTFORM). A candidate
|
||||
;; is a variable that is only passed to `funcall' or `apply'.
|
||||
(defvar cconv-lambda-candidates)
|
||||
|
||||
;; Alist associating to each function body the list of its free variables.
|
||||
(defvar cconv-freevars-alist)
|
||||
(defvar cconv-freevars-alist
|
||||
;; Alist associating to each function body the list of its free variables.
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defun cconv-closure-convert (form)
|
||||
|
|
@ -144,25 +147,13 @@ is less than this number.")
|
|||
Returns a form where all lambdas don't have any free variables."
|
||||
;; (message "Entering cconv-closure-convert...")
|
||||
(let ((cconv-freevars-alist '())
|
||||
(cconv-lambda-candidates '())
|
||||
(cconv-captured+mutated '()))
|
||||
(cconv-var-classification '()))
|
||||
;; Analyze form - fill these variables with new information.
|
||||
(cconv-analyze-form form '())
|
||||
(setq cconv-freevars-alist (nreverse cconv-freevars-alist))
|
||||
(prog1 (cconv-convert form nil nil) ; Env initially empty.
|
||||
(cl-assert (null cconv-freevars-alist)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun cconv-warnings-only (form)
|
||||
"Add the warnings that closure conversion would encounter."
|
||||
(let ((cconv-freevars-alist '())
|
||||
(cconv-lambda-candidates '())
|
||||
(cconv-captured+mutated '()))
|
||||
;; Analyze form - fill these variables with new information.
|
||||
(cconv-analyze-form form '())
|
||||
;; But don't perform the closure conversion.
|
||||
form))
|
||||
|
||||
(defconst cconv--dummy-var (make-symbol "ignored"))
|
||||
|
||||
(defun cconv--set-diff (s1 s2)
|
||||
|
|
@ -261,28 +252,55 @@ Returns a form where all lambdas don't have any free variables."
|
|||
(nthcdr 3 mapping)))))
|
||||
new-env))
|
||||
|
||||
(defun cconv--warn-unused-msg (var varkind)
|
||||
(unless (or ;; Uninterned symbols typically come from macro-expansion, so
|
||||
;; it is often non-trivial for the programmer to avoid such
|
||||
;; unused vars.
|
||||
(not (intern-soft var))
|
||||
(eq ?_ (aref (symbol-name var) 0))
|
||||
;; As a special exception, ignore "ignore".
|
||||
(eq var 'ignored))
|
||||
(let ((suggestions (help-uni-confusable-suggestions (symbol-name var))))
|
||||
(format "Unused lexical %s `%S'%s"
|
||||
varkind var
|
||||
(if suggestions (concat "\n " suggestions) "")))))
|
||||
|
||||
(define-inline cconv--var-classification (binder form)
|
||||
(inline-quote
|
||||
(alist-get (cons ,binder ,form) cconv-var-classification
|
||||
nil nil #'equal)))
|
||||
|
||||
(defun cconv--convert-funcbody (funargs funcbody env parentform)
|
||||
"Run `cconv-convert' on FUNCBODY, the forms of a lambda expression.
|
||||
PARENTFORM is the form containing the lambda expression. ENV is a
|
||||
lexical environment (same format as for `cconv-convert'), not
|
||||
including FUNARGS, the function's argument list. Return a list
|
||||
of converted forms."
|
||||
(let ((letbind ()))
|
||||
(let ((wrappers ()))
|
||||
(dolist (arg funargs)
|
||||
(if (not (member (cons (list arg) parentform) cconv-captured+mutated))
|
||||
(if (assq arg env) (push `(,arg . nil) env))
|
||||
(push `(,arg . (car-safe ,arg)) env)
|
||||
(push `(,arg (list ,arg)) letbind)))
|
||||
(pcase (cconv--var-classification (list arg) parentform)
|
||||
(:captured+mutated
|
||||
(push `(,arg . (car-safe ,arg)) env)
|
||||
(push (lambda (body) `(let ((,arg (list ,arg))) ,body)) wrappers))
|
||||
((and :unused
|
||||
(let (and (pred stringp) msg)
|
||||
(cconv--warn-unused-msg arg "argument")))
|
||||
(if (assq arg env) (push `(,arg . nil) env)) ;FIXME: Is it needed?
|
||||
(push (lambda (body) (macroexp--warn-wrap msg body)) wrappers))
|
||||
(_
|
||||
(if (assq arg env) (push `(,arg . nil) env)))))
|
||||
(setq funcbody (mapcar (lambda (form)
|
||||
(cconv-convert form env nil))
|
||||
funcbody))
|
||||
(if letbind
|
||||
(if wrappers
|
||||
(let ((special-forms '()))
|
||||
;; Keep special forms at the beginning of the body.
|
||||
(while (or (stringp (car funcbody)) ;docstring.
|
||||
(memq (car-safe (car funcbody)) '(interactive declare)))
|
||||
(push (pop funcbody) special-forms))
|
||||
`(,@(nreverse special-forms) (let ,letbind . ,funcbody)))
|
||||
(let ((body (macroexp-progn funcbody)))
|
||||
(dolist (wrapper wrappers) (setq body (funcall wrapper body)))
|
||||
`(,@(nreverse special-forms) ,@(macroexp-unprogn body))))
|
||||
funcbody)))
|
||||
|
||||
(defun cconv-convert (form env extend)
|
||||
|
|
@ -340,46 +358,58 @@ places where they originally did not directly appear."
|
|||
(setq value (cadr binder))
|
||||
(car binder)))
|
||||
(new-val
|
||||
(cond
|
||||
;; Check if var is a candidate for lambda lifting.
|
||||
((and (member (cons binder form) cconv-lambda-candidates)
|
||||
(progn
|
||||
(cl-assert (and (eq (car value) 'function)
|
||||
(eq (car (cadr value)) 'lambda)))
|
||||
(cl-assert (equal (cddr (cadr value))
|
||||
(caar cconv-freevars-alist)))
|
||||
;; Peek at the freevars to decide whether to λ-lift.
|
||||
(let* ((fvs (cdr (car cconv-freevars-alist)))
|
||||
(fun (cadr value))
|
||||
(funargs (cadr fun))
|
||||
(funcvars (append fvs funargs)))
|
||||
(pcase (cconv--var-classification binder form)
|
||||
;; Check if var is a candidate for lambda lifting.
|
||||
((and :lambda-candidate
|
||||
(guard
|
||||
(progn
|
||||
(cl-assert (and (eq (car value) 'function)
|
||||
(eq (car (cadr value)) 'lambda)))
|
||||
(cl-assert (equal (cddr (cadr value))
|
||||
(caar cconv-freevars-alist)))
|
||||
;; Peek at the freevars to decide whether to λ-lift.
|
||||
(let* ((fvs (cdr (car cconv-freevars-alist)))
|
||||
(fun (cadr value))
|
||||
(funargs (cadr fun))
|
||||
(funcvars (append fvs funargs)))
|
||||
; lambda lifting condition
|
||||
(and fvs (>= cconv-liftwhen (length funcvars))))))
|
||||
(and fvs (>= cconv-liftwhen
|
||||
(length funcvars)))))))
|
||||
; Lift.
|
||||
(let* ((fvs (cdr (pop cconv-freevars-alist)))
|
||||
(fun (cadr value))
|
||||
(funargs (cadr fun))
|
||||
(funcvars (append fvs funargs))
|
||||
(funcbody (cddr fun))
|
||||
(funcbody-env ()))
|
||||
(push `(,var . (apply-partially ,var . ,fvs)) new-env)
|
||||
(dolist (fv fvs)
|
||||
(cl-pushnew fv new-extend)
|
||||
(if (and (eq 'car-safe (car-safe (cdr (assq fv env))))
|
||||
(not (memq fv funargs)))
|
||||
(push `(,fv . (car-safe ,fv)) funcbody-env)))
|
||||
`(function (lambda ,funcvars .
|
||||
,(cconv--convert-funcbody
|
||||
funargs funcbody funcbody-env value)))))
|
||||
(let* ((fvs (cdr (pop cconv-freevars-alist)))
|
||||
(fun (cadr value))
|
||||
(funargs (cadr fun))
|
||||
(funcvars (append fvs funargs))
|
||||
(funcbody (cddr fun))
|
||||
(funcbody-env ()))
|
||||
(push `(,var . (apply-partially ,var . ,fvs)) new-env)
|
||||
(dolist (fv fvs)
|
||||
(cl-pushnew fv new-extend)
|
||||
(if (and (eq 'car-safe (car-safe (cdr (assq fv env))))
|
||||
(not (memq fv funargs)))
|
||||
(push `(,fv . (car-safe ,fv)) funcbody-env)))
|
||||
`(function (lambda ,funcvars .
|
||||
,(cconv--convert-funcbody
|
||||
funargs funcbody funcbody-env value)))))
|
||||
|
||||
;; Check if it needs to be turned into a "ref-cell".
|
||||
((member (cons binder form) cconv-captured+mutated)
|
||||
(:captured+mutated
|
||||
;; Declared variable is mutated and captured.
|
||||
(push `(,var . (car-safe ,var)) new-env)
|
||||
`(list ,(cconv-convert value env extend)))
|
||||
|
||||
;; Check if it needs to be turned into a "ref-cell".
|
||||
(:unused
|
||||
;; Declared variable is unused.
|
||||
(if (assq var new-env) (push `(,var) new-env)) ;FIXME:Needed?
|
||||
(let ((newval
|
||||
`(ignore ,(cconv-convert value env extend)))
|
||||
(msg (cconv--warn-unused-msg var "variable")))
|
||||
(if (null msg) newval
|
||||
(macroexp--warn-wrap msg newval))))
|
||||
|
||||
;; Normal default case.
|
||||
(t
|
||||
(_
|
||||
(if (assq var new-env) (push `(,var) new-env))
|
||||
(cconv-convert value env extend)))))
|
||||
|
||||
|
|
@ -464,22 +494,28 @@ places where they originally did not directly appear."
|
|||
|
||||
; condition-case
|
||||
(`(condition-case ,var ,protected-form . ,handlers)
|
||||
`(condition-case ,var
|
||||
,(cconv-convert protected-form env extend)
|
||||
,@(let* ((cm (and var (member (cons (list var) form)
|
||||
cconv-captured+mutated)))
|
||||
(newenv
|
||||
(cond (cm (cons `(,var . (car-save ,var)) env))
|
||||
((assq var env) (cons `(,var) env))
|
||||
(t env))))
|
||||
(mapcar
|
||||
(let* ((class (and var (cconv--var-classification (list var) form)))
|
||||
(newenv
|
||||
(cond ((eq class :captured+mutated)
|
||||
(cons `(,var . (car-save ,var)) env))
|
||||
((assq var env) (cons `(,var) env))
|
||||
(t env)))
|
||||
(msg (when (eq class :unused)
|
||||
(cconv--warn-unused-msg var "variable")))
|
||||
(newprotform (cconv-convert protected-form env extend)))
|
||||
`(condition-case ,var
|
||||
,(if msg
|
||||
(macroexp--warn-wrap msg newprotform)
|
||||
newprotform)
|
||||
,@(mapcar
|
||||
(lambda (handler)
|
||||
`(,(car handler)
|
||||
,@(let ((body
|
||||
(mapcar (lambda (form)
|
||||
(cconv-convert form newenv extend))
|
||||
(cdr handler))))
|
||||
(if (not cm) body
|
||||
(if (not (eq class :captured+mutated))
|
||||
body
|
||||
`((let ((,var (list ,var))) ,@body))))))
|
||||
handlers))))
|
||||
|
||||
|
|
@ -563,29 +599,21 @@ FORM is the parent form that binds this var."
|
|||
(`(,_ nil nil nil nil) nil)
|
||||
(`((,(and var (guard (eq ?_ (aref (symbol-name var) 0)))) . ,_)
|
||||
,_ ,_ ,_ ,_)
|
||||
;; FIXME: Convert this warning to use `macroexp--warn-wrap'
|
||||
;; so as to give better position information.
|
||||
(byte-compile-warn
|
||||
"%s `%S' not left unused" varkind var)))
|
||||
(pcase vardata
|
||||
(`((,var . ,_) nil ,_ ,_ nil)
|
||||
;; FIXME: This gives warnings in the wrong order, with imprecise line
|
||||
;; numbers and without function name info.
|
||||
(unless (or ;; Uninterned symbols typically come from macro-expansion, so
|
||||
;; it is often non-trivial for the programmer to avoid such
|
||||
;; unused vars.
|
||||
(not (intern-soft var))
|
||||
(eq ?_ (aref (symbol-name var) 0))
|
||||
;; As a special exception, ignore "ignore".
|
||||
(eq var 'ignored))
|
||||
(let ((suggestions (help-uni-confusable-suggestions (symbol-name var))))
|
||||
(byte-compile-warn "Unused lexical %s `%S'%s"
|
||||
varkind var
|
||||
(if suggestions (concat "\n " suggestions) "")))))
|
||||
(`(,binder nil ,_ ,_ nil)
|
||||
(push (cons (cons binder form) :unused) cconv-var-classification))
|
||||
;; If it's unused, there's no point converting it into a cons-cell, even if
|
||||
;; it's captured and mutated.
|
||||
(`(,binder ,_ t t ,_)
|
||||
(push (cons binder form) cconv-captured+mutated))
|
||||
(push (cons (cons binder form) :captured+mutated)
|
||||
cconv-var-classification))
|
||||
(`(,(and binder `(,_ (function (lambda . ,_)))) nil nil nil t)
|
||||
(push (cons binder form) cconv-lambda-candidates))))
|
||||
(push (cons (cons binder form) :lambda-candidate)
|
||||
cconv-var-classification))))
|
||||
|
||||
(defun cconv--analyze-function (args body env parentform)
|
||||
(let* ((newvars nil)
|
||||
|
|
@ -638,8 +666,7 @@ Analyze lambdas if they are suitable for lambda lifting.
|
|||
- ENV is an alist mapping each enclosing lexical variable to its info.
|
||||
I.e. each element has the form (VAR . (READ MUTATED CAPTURED CALLED)).
|
||||
This function does not return anything but instead fills the
|
||||
`cconv-captured+mutated' and `cconv-lambda-candidates' variables
|
||||
and updates the data stored in ENV."
|
||||
`cconv-var-classification' variable and updates the data stored in ENV."
|
||||
(pcase form
|
||||
; let special form
|
||||
(`(,(and (or 'let* 'let) letsym) ,binders . ,body-forms)
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@ don't move point."
|
|||
;; definition ends prematurely.
|
||||
(end-of-file)))
|
||||
(`(,(or 'defun 'defvar 'defcustom 'defmacro 'defconst 'defsubst 'defadvice
|
||||
'cl-defun 'cl-defgeneric 'cl-defmethod 'cl-defmacro)
|
||||
'cl-defun 'cl-defgeneric 'cl-defmacro)
|
||||
,(pred symbolp)
|
||||
;; Require an initializer, i.e. ignore single-argument `defvar'
|
||||
;; forms, which never have a doc string.
|
||||
|
|
@ -942,6 +942,25 @@ don't move point."
|
|||
;; initializer or argument list.
|
||||
(forward-sexp 3)
|
||||
(skip-chars-forward " \n\t")
|
||||
t)
|
||||
(`(,'cl-defmethod
|
||||
,(pred symbolp)
|
||||
. ,rest)
|
||||
(down-list)
|
||||
(forward-sexp (pcase (car rest)
|
||||
;; No qualifier, so skip like we would have skipped in
|
||||
;; the first clause of the outer `pcase'.
|
||||
((pred listp) 3)
|
||||
(':extra
|
||||
;; Skip the :extra qualifier together with its string too.
|
||||
;; Skip any additional qualifier.
|
||||
(if (memq (nth 2 rest) '(:around :before :after))
|
||||
6
|
||||
5))
|
||||
;; Skip :before, :after or :around qualifier too.
|
||||
((or ':around ':before ':after)
|
||||
4)))
|
||||
(skip-chars-forward " \n\t")
|
||||
t)))
|
||||
|
||||
;;;###autoload
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ strings case-insensitively."
|
|||
(defun cl--mapcar-many (cl-func cl-seqs &optional acc)
|
||||
(if (cdr (cdr cl-seqs))
|
||||
(let* ((cl-res nil)
|
||||
(cl-n (apply 'min (mapcar 'length cl-seqs)))
|
||||
(cl-n (apply #'min (mapcar #'length cl-seqs)))
|
||||
(cl-i 0)
|
||||
(cl-args (copy-sequence cl-seqs))
|
||||
cl-p1 cl-p2)
|
||||
|
|
@ -131,7 +131,7 @@ strings case-insensitively."
|
|||
"Map a FUNCTION across one or more SEQUENCEs, returning a sequence.
|
||||
TYPE is the sequence type to return.
|
||||
\n(fn TYPE FUNCTION SEQUENCE...)"
|
||||
(let ((cl-res (apply 'cl-mapcar cl-func cl-seq cl-rest)))
|
||||
(let ((cl-res (apply #'cl-mapcar cl-func cl-seq cl-rest)))
|
||||
(and cl-type (cl-coerce cl-res cl-type))))
|
||||
|
||||
;;;###autoload
|
||||
|
|
@ -190,14 +190,14 @@ the elements themselves.
|
|||
"Like `cl-mapcar', but nconc's together the values returned by the function.
|
||||
\n(fn FUNCTION SEQUENCE...)"
|
||||
(if cl-rest
|
||||
(apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest))
|
||||
(apply #'nconc (apply #'cl-mapcar cl-func cl-seq cl-rest))
|
||||
(mapcan cl-func cl-seq)))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-mapcon (cl-func cl-list &rest cl-rest)
|
||||
"Like `cl-maplist', but nconc's together the values returned by the function.
|
||||
\n(fn FUNCTION LIST...)"
|
||||
(apply 'nconc (apply 'cl-maplist cl-func cl-list cl-rest)))
|
||||
(apply #'nconc (apply #'cl-maplist cl-func cl-list cl-rest)))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-some (cl-pred cl-seq &rest cl-rest)
|
||||
|
|
@ -236,13 +236,13 @@ non-nil value.
|
|||
(defun cl-notany (cl-pred cl-seq &rest cl-rest)
|
||||
"Return true if PREDICATE is false of every element of SEQ or SEQs.
|
||||
\n(fn PREDICATE SEQ...)"
|
||||
(not (apply 'cl-some cl-pred cl-seq cl-rest)))
|
||||
(not (apply #'cl-some cl-pred cl-seq cl-rest)))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl-notevery (cl-pred cl-seq &rest cl-rest)
|
||||
"Return true if PREDICATE is false of some element of SEQ or SEQs.
|
||||
\n(fn PREDICATE SEQ...)"
|
||||
(not (apply 'cl-every cl-pred cl-seq cl-rest)))
|
||||
(not (apply #'cl-every cl-pred cl-seq cl-rest)))
|
||||
|
||||
;;;###autoload
|
||||
(defun cl--map-keymap-recursively (cl-func-rec cl-map &optional cl-base)
|
||||
|
|
@ -693,12 +693,11 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
|
|||
"Expand macros in FORM and insert the pretty-printed result."
|
||||
(declare (advertised-calling-convention (form) "27.1"))
|
||||
(message "Expanding...")
|
||||
(let ((byte-compile-macro-environment nil))
|
||||
(setq form (macroexpand-all form))
|
||||
(message "Formatting...")
|
||||
(prog1
|
||||
(cl-prettyprint form)
|
||||
(message ""))))
|
||||
(setq form (macroexpand-all form))
|
||||
(message "Formatting...")
|
||||
(prog1
|
||||
(cl-prettyprint form)
|
||||
(message "")))
|
||||
|
||||
;;; Integration into the online help system.
|
||||
|
||||
|
|
|
|||
|
|
@ -425,6 +425,16 @@ the specializer used will be the one returned by BODY."
|
|||
(defun cl-generic--method-qualifier-p (x)
|
||||
(not (listp x)))
|
||||
|
||||
(defun cl--defmethod-doc-pos ()
|
||||
"Return the index of the docstring for a `cl-defmethod'.
|
||||
Presumes point is at the end of the `cl-defmethod' symbol."
|
||||
(save-excursion
|
||||
(let ((n 2))
|
||||
(while (and (ignore-errors (forward-sexp 1) t)
|
||||
(not (eq (char-before) ?\))))
|
||||
(cl-incf n))
|
||||
n)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro cl-defmethod (name args &rest body)
|
||||
"Define a new method for generic function NAME.
|
||||
|
|
@ -445,8 +455,12 @@ all methods of NAME have to use the same set of arguments for dispatch.
|
|||
Each dispatch argument and TYPE are specified in ARGS where the corresponding
|
||||
formal argument appears as (VAR TYPE) rather than just VAR.
|
||||
|
||||
The optional second argument QUALIFIER is a specifier that
|
||||
modifies how the method is combined with other methods, including:
|
||||
The optional EXTRA element, on the form `:extra STRING', allows
|
||||
you to add more methods for the same specializers and qualifiers.
|
||||
These are distinguished by STRING.
|
||||
|
||||
The optional argument QUALIFIER is a specifier that modifies how
|
||||
the method is combined with other methods, including:
|
||||
:before - Method will be called before the primary
|
||||
:after - Method will be called after the primary
|
||||
:around - Method will be called around everything else
|
||||
|
|
@ -463,8 +477,8 @@ method to be applicable.
|
|||
The set of acceptable TYPEs (also called \"specializers\") is defined
|
||||
\(and can be extended) by the various methods of `cl-generic-generalizers'.
|
||||
|
||||
\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
|
||||
(declare (doc-string 3) (indent defun)
|
||||
\(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
|
||||
(declare (doc-string cl--defmethod-doc-pos) (indent defun)
|
||||
(debug
|
||||
(&define ; this means we are defining something
|
||||
[&name [sexp ;Allow (setf ...) additionally to symbols.
|
||||
|
|
@ -487,7 +501,7 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
|
|||
(or (not (fboundp 'byte-compile-warning-enabled-p))
|
||||
(byte-compile-warning-enabled-p 'obsolete name))
|
||||
(let* ((obsolete (get name 'byte-obsolete-info)))
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(macroexp--obsolete-warning name obsolete "generic function")
|
||||
nil)))
|
||||
;; You could argue that `defmethod' modifies rather than defines the
|
||||
|
|
|
|||
|
|
@ -565,7 +565,7 @@ its argument list allows full Common Lisp conventions."
|
|||
,(length (cl-ldiff args p)))
|
||||
exactarg (not (eq args p)))))
|
||||
(while (and args (not (memq (car args) cl--lambda-list-keywords)))
|
||||
(let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car)
|
||||
(let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car-safe)
|
||||
restarg)))
|
||||
(cl--do-arglist
|
||||
(pop args)
|
||||
|
|
@ -723,7 +723,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
|
|||
(defun cl--compile-time-too (form)
|
||||
(or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
|
||||
(setq form (macroexpand
|
||||
form (cons '(cl-eval-when) byte-compile-macro-environment))))
|
||||
form (cons '(cl-eval-when) macroexpand-all-environment))))
|
||||
(cond ((eq (car-safe form) 'progn)
|
||||
(cons 'progn (mapcar #'cl--compile-time-too (cdr form))))
|
||||
((eq (car-safe form) 'cl-eval-when)
|
||||
|
|
@ -2298,7 +2298,7 @@ of `cl-symbol-macrolet' to additionally expand symbol macros."
|
|||
;; The behavior of CL made sense in a dynamically scoped
|
||||
;; language, but nowadays, lexical scoping semantics is more often
|
||||
;; expected.
|
||||
(`(,(or 'let 'let*) . ,(or `(,bindings . ,body) dontcare))
|
||||
(`(,(or 'let 'let*) . ,(or `(,bindings . ,body) pcase--dontcare))
|
||||
(let ((nbs ()) (found nil))
|
||||
(dolist (binding bindings)
|
||||
(let* ((var (if (symbolp binding) binding (car binding)))
|
||||
|
|
@ -2393,7 +2393,7 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
|
|||
(append bindings venv))
|
||||
macroexpand-all-environment))))
|
||||
(if malformed-bindings
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format-message "Malformed `cl-symbol-macrolet' binding(s): %S"
|
||||
(nreverse malformed-bindings))
|
||||
expansion)
|
||||
|
|
@ -2511,12 +2511,12 @@ Example:
|
|||
'(nil byte-compile-inline-expand))
|
||||
(error "%s already has a byte-optimizer, can't make it inline"
|
||||
(car spec)))
|
||||
(put (car spec) 'byte-optimizer 'byte-compile-inline-expand)))
|
||||
(put (car spec) 'byte-optimizer #'byte-compile-inline-expand)))
|
||||
|
||||
((eq (car-safe spec) 'notinline)
|
||||
(while (setq spec (cdr spec))
|
||||
(if (eq (get (car spec) 'byte-optimizer)
|
||||
'byte-compile-inline-expand)
|
||||
#'byte-compile-inline-expand)
|
||||
(put (car spec) 'byte-optimizer nil))))
|
||||
|
||||
((eq (car-safe spec) 'optimize)
|
||||
|
|
@ -3062,7 +3062,7 @@ Supported keywords for slots are:
|
|||
forms)
|
||||
(when (cl-oddp (length desc))
|
||||
(push
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format "Missing value for option `%S' of slot `%s' in struct %s!"
|
||||
(car (last desc)) slot name)
|
||||
'nil)
|
||||
|
|
@ -3071,7 +3071,7 @@ Supported keywords for slots are:
|
|||
(not (keywordp (car desc))))
|
||||
(let ((kw (car defaults)))
|
||||
(push
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format " I'll take `%s' to be an option rather than a default value."
|
||||
kw)
|
||||
'nil)
|
||||
|
|
@ -3287,7 +3287,6 @@ does not contain SLOT-NAME."
|
|||
(signal 'cl-struct-unknown-slot (list struct-type slot-name))))
|
||||
|
||||
(defvar byte-compile-function-environment)
|
||||
(defvar byte-compile-macro-environment)
|
||||
|
||||
(defun cl--macroexp-fboundp (sym)
|
||||
"Return non-nil if SYM will be bound when we run the code.
|
||||
|
|
@ -3295,7 +3294,7 @@ Of course, we really can't know that for sure, so it's just a heuristic."
|
|||
(or (fboundp sym)
|
||||
(and (macroexp-compiling-p)
|
||||
(or (cdr (assq sym byte-compile-function-environment))
|
||||
(cdr (assq sym byte-compile-macro-environment))))))
|
||||
(cdr (assq sym macroexpand-all-environment))))))
|
||||
|
||||
(pcase-dolist (`(,type . ,pred)
|
||||
;; Mostly kept in alphabetical order.
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
(defsubst easy-menu-intern (s)
|
||||
(if (stringp s) (intern s) s))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro easy-menu-define (symbol maps doc menu)
|
||||
"Define a pop-up menu and/or menu bar menu specified by MENU.
|
||||
If SYMBOL is non-nil, define SYMBOL as a function to pop up the
|
||||
|
|
@ -166,7 +165,6 @@ This is expected to be bound to a mouse event."
|
|||
""))
|
||||
(cons menu props)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun easy-menu-do-define (symbol maps doc menu)
|
||||
;; We can't do anything that might differ between Emacs dialects in
|
||||
;; `easy-menu-define' in order to make byte compiled files
|
||||
|
|
@ -192,7 +190,11 @@ This is expected to be bound to a mouse event."
|
|||
(function-put symbol 'completion-predicate #'ignore))
|
||||
(dolist (map (if (keymapp maps) (list maps) maps))
|
||||
(define-key map
|
||||
(vector 'menu-bar (easy-menu-intern (car menu)))
|
||||
(vector 'menu-bar (if (symbolp (car menu))
|
||||
(car menu)
|
||||
;; If a string, then use the downcased
|
||||
;; version for greater backwards compatibility.
|
||||
(intern (downcase (car menu)))))
|
||||
(easy-menu-binding keymap (car menu))))))
|
||||
|
||||
(defun easy-menu-filter-return (menu &optional name)
|
||||
|
|
@ -218,7 +220,6 @@ If NAME is provided, it is used for the keymap."
|
|||
If it holds a list, this is expected to be a list of keys already seen in the
|
||||
menu we're processing. Else it means we're not processing a menu.")
|
||||
|
||||
;;;###autoload
|
||||
(defun easy-menu-create-menu (menu-name menu-items)
|
||||
"Create a menu called MENU-NAME with items described in MENU-ITEMS.
|
||||
MENU-NAME is a string, the name of the menu. MENU-ITEMS is a list of items
|
||||
|
|
@ -474,7 +475,6 @@ When non-nil, NOEXP indicates that CALLBACK cannot be an expression
|
|||
(eval `(lambda () (interactive) ,callback) t)))
|
||||
command))
|
||||
|
||||
;;;###autoload
|
||||
(defun easy-menu-change (path name items &optional before map)
|
||||
"Change menu found at PATH as item NAME to contain ITEMS.
|
||||
PATH is a list of strings for locating the menu that
|
||||
|
|
|
|||
|
|
@ -729,7 +729,7 @@ Argument FN is the function calling this verifier."
|
|||
(pcase slot
|
||||
((and (or `',name (and name (pred keywordp)))
|
||||
(guard (not (memq name eieio--known-slot-names))))
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format-message "Unknown slot `%S'" name) exp 'compile-only))
|
||||
(_ exp))))
|
||||
(gv-setter eieio-oset))
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ This method is obsolete."
|
|||
(lambda (whole)
|
||||
(if (not (stringp (car slots)))
|
||||
whole
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format "Obsolete name arg %S to constructor %S"
|
||||
(car slots) (car whole))
|
||||
;; Keep the name arg, for backward compatibility,
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ displayed."
|
|||
;; continue standard unloading
|
||||
nil)
|
||||
|
||||
(cl-defmethod loadhist-unload-element :before :extra "elp" ((x (head defun)))
|
||||
(cl-defmethod loadhist-unload-element :extra "elp" :before ((x (head defun)))
|
||||
"Un-instrument before unloading a function."
|
||||
(elp-restore-function (cdr x)))
|
||||
|
||||
|
|
|
|||
|
|
@ -277,14 +277,7 @@ It should only be stopped when ran from inside ert--run-test-internal."
|
|||
(let ((form
|
||||
;; catch macroexpansion errors
|
||||
(condition-case err
|
||||
(macroexpand-all form
|
||||
(append (bound-and-true-p
|
||||
byte-compile-macro-environment)
|
||||
(cond
|
||||
((boundp 'macroexpand-all-environment)
|
||||
macroexpand-all-environment)
|
||||
((boundp 'cl-macro-environment)
|
||||
cl-macro-environment))))
|
||||
(macroexpand-all form macroexpand-all-environment)
|
||||
(error `(signal ',(car err) ',(cdr err))))))
|
||||
(cond
|
||||
((or (atom form) (ert--special-operator-p (car form)))
|
||||
|
|
@ -1550,7 +1543,7 @@ Ran \\([0-9]+\\) tests, \\([0-9]+\\) results as expected\
|
|||
(message "------------------")
|
||||
(setq tests (sort tests (lambda (x y) (> (car x) (car y)))))
|
||||
(when (< high (length tests)) (setcdr (nthcdr (1- high) tests) nil))
|
||||
(message "%s" (mapconcat 'cdr tests "\n")))
|
||||
(message "%s" (mapconcat #'cdr tests "\n")))
|
||||
;; More details on hydra, where the logs are harder to get to.
|
||||
(when (and (getenv "EMACS_HYDRA_CI")
|
||||
(not (zerop (+ nunexpected nskipped))))
|
||||
|
|
@ -2077,7 +2070,7 @@ and how to display message."
|
|||
(ert-run-tests selector listener t)))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'ert 'ert-run-tests-interactively)
|
||||
(defalias 'ert #'ert-run-tests-interactively)
|
||||
|
||||
|
||||
;;; Simple view mode for auxiliary information like stack traces or
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ binding mode."
|
|||
;; dynamic binding mode as well.
|
||||
(eq (car-safe code) 'cons))
|
||||
code
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
"Use of gv-ref probably requires lexical-binding"
|
||||
code))))
|
||||
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ See Info node `(elisp)Defining Functions' for more details."
|
|||
'(throw 'inline--just-use
|
||||
;; FIXME: This would inf-loop by calling us right back when
|
||||
;; macroexpand-all recurses to expand inline--form.
|
||||
;; (macroexp--warn-and-return (format ,@args)
|
||||
;; (macroexp-warn-and-return (format ,@args)
|
||||
;; inline--form)
|
||||
inline--form))
|
||||
|
||||
|
|
|
|||
|
|
@ -740,25 +740,24 @@ font-lock keywords will not be case sensitive."
|
|||
;;; Generic Lisp mode.
|
||||
|
||||
(defvar lisp-mode-map
|
||||
(let ((map (make-sparse-keymap))
|
||||
(menu-map (make-sparse-keymap "Lisp")))
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map lisp-mode-shared-map)
|
||||
(define-key map "\e\C-x" 'lisp-eval-defun)
|
||||
(define-key map "\C-c\C-z" 'run-lisp)
|
||||
(bindings--define-key map [menu-bar lisp] (cons "Lisp" menu-map))
|
||||
(bindings--define-key menu-map [run-lisp]
|
||||
'(menu-item "Run inferior Lisp" run-lisp
|
||||
:help "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'"))
|
||||
(bindings--define-key menu-map [ev-def]
|
||||
'(menu-item "Eval defun" lisp-eval-defun
|
||||
:help "Send the current defun to the Lisp process made by M-x run-lisp"))
|
||||
(bindings--define-key menu-map [ind-sexp]
|
||||
'(menu-item "Indent sexp" indent-sexp
|
||||
:help "Indent each line of the list starting just after point"))
|
||||
map)
|
||||
"Keymap for ordinary Lisp mode.
|
||||
All commands in `lisp-mode-shared-map' are inherited by this map.")
|
||||
|
||||
(easy-menu-define lisp-mode-menu lisp-mode-map
|
||||
"Menu for ordinary Lisp mode."
|
||||
'("Lisp"
|
||||
["Indent sexp" indent-sexp
|
||||
:help "Indent each line of the list starting just after point"]
|
||||
["Eval defun" lisp-eval-defun
|
||||
:help "Send the current defun to the Lisp process made by M-x run-lisp"]
|
||||
["Run inferior Lisp" run-lisp
|
||||
:help "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'"]))
|
||||
|
||||
(define-derived-mode lisp-mode lisp-data-mode "Lisp"
|
||||
"Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
|
||||
Commands:
|
||||
|
|
@ -1372,7 +1371,8 @@ and initial semicolons."
|
|||
fill-column)))
|
||||
(save-restriction
|
||||
(save-excursion
|
||||
(let ((ppss (syntax-ppss)))
|
||||
(let ((ppss (syntax-ppss))
|
||||
(start (point)))
|
||||
;; If we're in a string, then narrow (roughly) to that
|
||||
;; string before filling. This avoids filling Lisp
|
||||
;; statements that follow the string.
|
||||
|
|
@ -1387,6 +1387,8 @@ and initial semicolons."
|
|||
t))
|
||||
(narrow-to-region (ppss-comment-or-string-start ppss)
|
||||
(point))))
|
||||
;; Move back to where we were.
|
||||
(goto-char start)
|
||||
(fill-paragraph justify)))))
|
||||
;; Never return nil.
|
||||
t))
|
||||
|
|
|
|||
|
|
@ -135,28 +135,33 @@ Other uses risk returning non-nil value that point to the wrong file."
|
|||
|
||||
(defvar macroexp--warned (make-hash-table :test #'equal :weakness 'key))
|
||||
|
||||
(defun macroexp--warn-and-return (msg form &optional compile-only)
|
||||
(defun macroexp--warn-wrap (msg form)
|
||||
(let ((when-compiled (lambda () (byte-compile-warn "%s" msg))))
|
||||
(cond
|
||||
((null msg) form)
|
||||
((macroexp-compiling-p)
|
||||
(if (and (consp form) (gethash form macroexp--warned))
|
||||
;; Already wrapped this exp with a warning: avoid inf-looping
|
||||
;; where we keep adding the same warning onto `form' because
|
||||
;; macroexpand-all gets right back to macroexpanding `form'.
|
||||
form
|
||||
(puthash form form macroexp--warned)
|
||||
`(progn
|
||||
(macroexp--funcall-if-compiled ',when-compiled)
|
||||
,form)))
|
||||
(t
|
||||
(unless compile-only
|
||||
(message "%sWarning: %s"
|
||||
(if (stringp load-file-name)
|
||||
(concat (file-relative-name load-file-name) ": ")
|
||||
"")
|
||||
msg))
|
||||
form))))
|
||||
`(progn
|
||||
(macroexp--funcall-if-compiled ',when-compiled)
|
||||
,form)))
|
||||
|
||||
(define-obsolete-function-alias 'macroexp--warn-and-return
|
||||
#'macroexp-warn-and-return "28.1")
|
||||
(defun macroexp-warn-and-return (msg form &optional compile-only)
|
||||
(cond
|
||||
((null msg) form)
|
||||
((macroexp-compiling-p)
|
||||
(if (and (consp form) (gethash form macroexp--warned))
|
||||
;; Already wrapped this exp with a warning: avoid inf-looping
|
||||
;; where we keep adding the same warning onto `form' because
|
||||
;; macroexpand-all gets right back to macroexpanding `form'.
|
||||
form
|
||||
(puthash form form macroexp--warned)
|
||||
(macroexp--warn-wrap msg form)))
|
||||
(t
|
||||
(unless compile-only
|
||||
(message "%sWarning: %s"
|
||||
(if (stringp load-file-name)
|
||||
(concat (file-relative-name load-file-name) ": ")
|
||||
"")
|
||||
msg))
|
||||
form)))
|
||||
|
||||
(defun macroexp--obsolete-warning (fun obsolescence-data type)
|
||||
(let ((instead (car obsolescence-data))
|
||||
|
|
@ -205,7 +210,7 @@ Other uses risk returning non-nil value that point to the wrong file."
|
|||
(byte-compile-warning-enabled-p 'obsolete (car form))))
|
||||
(let* ((fun (car form))
|
||||
(obsolete (get fun 'byte-obsolete-info)))
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(macroexp--obsolete-warning
|
||||
fun obsolete
|
||||
(if (symbolp (symbol-function fun))
|
||||
|
|
@ -260,7 +265,7 @@ Other uses risk returning non-nil value that point to the wrong file."
|
|||
values (cdr values))))
|
||||
(setq arglist (cdr arglist)))
|
||||
(if values
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format (if (eq values 'too-few)
|
||||
"attempt to open-code `%s' with too few arguments"
|
||||
"attempt to open-code `%s' with too many arguments")
|
||||
|
|
@ -289,10 +294,12 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
macroexpand-all-environment)
|
||||
;; Normal form; get its expansion, and then expand arguments.
|
||||
(setq form (macroexp-macroexpand form macroexpand-all-environment))
|
||||
;; FIXME: It'd be nice to use `byte-optimize--pcase' here, but when
|
||||
;; I tried it, it broke the bootstrap :-(
|
||||
(pcase form
|
||||
(`(cond . ,clauses)
|
||||
(macroexp--cons 'cond (macroexp--all-clauses clauses) form))
|
||||
(`(condition-case . ,(or `(,err ,body . ,handlers) dontcare))
|
||||
(`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
|
||||
(macroexp--cons
|
||||
'condition-case
|
||||
(macroexp--cons err
|
||||
|
|
@ -309,12 +316,13 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
(cdr form))
|
||||
form))
|
||||
(`(,(or 'function 'quote) . ,_) form)
|
||||
(`(,(and fun (or 'let 'let*)) . ,(or `(,bindings . ,body) dontcare))
|
||||
(`(,(and fun (or 'let 'let*)) . ,(or `(,bindings . ,body)
|
||||
pcase--dontcare))
|
||||
(macroexp--cons fun
|
||||
(macroexp--cons (macroexp--all-clauses bindings 1)
|
||||
(if (null body)
|
||||
(macroexp-unprogn
|
||||
(macroexp--warn-and-return
|
||||
(macroexp-warn-and-return
|
||||
(format "Empty %s body" fun)
|
||||
nil t))
|
||||
(macroexp--all-forms body))
|
||||
|
|
@ -334,27 +342,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
form)
|
||||
(macroexp--expand-all newform))))
|
||||
|
||||
;; The following few cases are for normal function calls that
|
||||
;; are known to funcall one of their arguments. The byte
|
||||
;; compiler has traditionally handled these functions specially
|
||||
;; by treating a lambda expression quoted by `quote' as if it
|
||||
;; were quoted by `function'. We make the same transformation
|
||||
;; here, so that any code that cares about the difference will
|
||||
;; see the same transformation.
|
||||
;; First arg is a function:
|
||||
(`(,(and fun (or 'funcall 'apply 'mapcar 'mapatoms 'mapconcat 'mapc))
|
||||
',(and f `(lambda . ,_)) . ,args)
|
||||
(macroexp--warn-and-return
|
||||
(format "%s quoted with ' rather than with #'"
|
||||
(list 'lambda (nth 1 f) '...))
|
||||
(macroexp--expand-all `(,fun #',f . ,args))))
|
||||
;; Second arg is a function:
|
||||
(`(,(and fun (or 'sort)) ,arg1 ',(and f `(lambda . ,_)) . ,args)
|
||||
(macroexp--warn-and-return
|
||||
(format "%s quoted with ' rather than with #'"
|
||||
(list 'lambda (nth 1 f) '...))
|
||||
(macroexp--expand-all `(,fun ,arg1 #',f . ,args))))
|
||||
(`(funcall ,exp . ,args)
|
||||
(`(funcall . ,(or `(,exp . ,args) pcase--dontcare))
|
||||
(let ((eexp (macroexp--expand-all exp))
|
||||
(eargs (macroexp--all-forms args)))
|
||||
;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
|
||||
|
|
@ -363,10 +351,22 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
(`#',f (macroexp--expand-all `(,f . ,eargs)))
|
||||
(_ `(funcall ,eexp . ,eargs)))))
|
||||
(`(,func . ,_)
|
||||
;; Macro expand compiler macros. This cannot be delayed to
|
||||
;; byte-optimize-form because the output of the compiler-macro can
|
||||
;; use macros.
|
||||
(let ((handler (function-get func 'compiler-macro)))
|
||||
(let ((handler (function-get func 'compiler-macro))
|
||||
(funargs (function-get func 'funarg-positions)))
|
||||
;; Check functions quoted with ' rather than with #'
|
||||
(dolist (funarg funargs)
|
||||
(let ((arg (nth funarg form)))
|
||||
(when (and (eq 'quote (car-safe arg))
|
||||
(eq 'lambda (car-safe (cadr arg))))
|
||||
(setcar (nthcdr funarg form)
|
||||
(macroexp-warn-and-return
|
||||
(format "%S quoted with ' rather than with #'"
|
||||
(let ((f (cadr arg)))
|
||||
(if (symbolp f) f `(lambda ,(nth 1 f) ...))))
|
||||
arg)))))
|
||||
;; Macro expand compiler macros. This cannot be delayed to
|
||||
;; byte-optimize-form because the output of the compiler-macro can
|
||||
;; use macros.
|
||||
(if (null handler)
|
||||
;; No compiler macro. We just expand each argument (for
|
||||
;; setq/setq-default this works alright because the variable names
|
||||
|
|
@ -392,6 +392,18 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
|
||||
(_ form))))
|
||||
|
||||
;; Record which arguments expect functions, so we can warn when those
|
||||
;; are accidentally quoted with ' rather than with #'
|
||||
(dolist (f '(funcall apply mapcar mapatoms mapconcat mapc cl-mapcar maphash))
|
||||
(put f 'funarg-positions '(1)))
|
||||
(dolist (f '( add-hook remove-hook advice-remove advice--remove-function
|
||||
defalias fset global-set-key run-after-idle-timeout
|
||||
set-process-filter set-process-sentinel sort))
|
||||
(put f 'funarg-positions '(2)))
|
||||
(dolist (f '( advice-add define-key
|
||||
run-at-time run-with-idle-timer run-with-timer ))
|
||||
(put f 'funarg-positions '(3)))
|
||||
|
||||
;;;###autoload
|
||||
(defun macroexpand-all (form &optional environment)
|
||||
"Return result of expanding macros at all levels in FORM.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue