commit 6efa25d7b503a03c511d0ec75b47297c0efed3fa (HEAD, refs/remotes/origin/master) Author: Noam Postavsky Date: Thu Jun 1 22:54:09 2017 -0400 * etc/tutorials/TUTORIAL: Explain how to stop the tutorial (Bug#20371). diff --git a/etc/tutorials/TUTORIAL b/etc/tutorials/TUTORIAL index 40e1cf8480..3419c63c1f 100644 --- a/etc/tutorials/TUTORIAL +++ b/etc/tutorials/TUTORIAL @@ -12,6 +12,7 @@ write that in full each time, we'll use the following abbreviations: Important note: to end the Emacs session, type C-x C-c. (Two characters.) To quit a partially entered command, type C-g. +To stop the tutorial, type C-x k, then at the prompt. The characters ">>" at the left margin indicate directions for you to try using a command. For instance: <> commit 8de2581a64dac3785fc3877f7cd87c4164fd2936 Author: Paul Eggert Date: Thu Jun 1 16:03:12 2017 -0700 Limit format fields to more POSIX-like spec * doc/lispref/strings.texi (Formatting Strings): Don’t allow mixing numbered with unnumbered format specs. * src/editfns.c (styled_format): Don’t bother checking for field 0, since it doesn’t crash and the behavior is not specified. * test/src/editfns-tests.el (format-with-field): Adjust tests to match current doc. Add more tests for out-of-range fields. diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 4d33e55b01..e80e778bec 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -965,16 +965,13 @@ extra values to be formatted are ignored. decimal number immediately after the initial @samp{%}, followed by a literal dollar sign @samp{$}. It causes the format specification to convert the argument with the given number instead of the next -argument. Argument 1 is the argument just after the format. - - You can mix specifications with and without field numbers. A -specification without a field number that follows a specification with -a field number will convert the argument after the one specified by -the field number: +argument. Field numbers start at 1. A format can contain either +numbered or unnumbered format specifications but not both, except that +@samp{%%} can be mixed with numbered specifications. @example -(format "Argument %2$s, then %s, then %1$s" "x" "y" "z") - @result{} "Argument y, then z, then x" +(format "%2$s, %3$s, %%, %1$s" "x" "y" "z") + @result{} "y, z, %, x" @end example @cindex flags in format specifications diff --git a/src/editfns.c b/src/editfns.c index 1dbae8f5d4..29af25aab4 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3900,8 +3900,10 @@ where field is [0-9]+ followed by a literal dollar "$", flags is [+ #-0]+, width is [0-9]+, and precision is a literal period "." followed by [0-9]+. -If field is given, it must be a one-based argument number; the given -argument is substituted instead of the next one. +If a %-sequence is numbered with a field with positive value N, the +Nth argument is substituted instead of the next one. A format can +contain either numbered or unnumbered %-sequences but not both, except +that %% can be mixed with numbered %-sequences. The + flag character inserts a + before any positive number, while a space inserts a space before any positive number; these flags only @@ -4081,8 +4083,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) num = str2num (format, &num_end); if (*num_end == '$') { - if (num == 0) - error ("Invalid format field number 0"); n = num - 1; format = num_end + 1; } diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index c5923aaafb..54fb743e19 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -178,17 +178,33 @@ (concat (make-string 2048 ?X) "0"))))) (ert-deftest format-with-field () - (should (equal (format "First argument %2$s, then %s, then %1$s" 1 2 3) + (should (equal (format "First argument %2$s, then %3$s, then %1$s" 1 2 3) "First argument 2, then 3, then 1")) - (should (equal (format "a %2$s %d %1$d %2$S %d %d b" 11 "22" 33 44) + (should (equal (format "a %2$s %3$d %1$d %2$S %3$d %4$d b" 11 "22" 33 44) "a 22 33 11 \"22\" 33 44 b")) - (should (equal (format "a %08$s %s b" 1 2 3 4 5 6 7 8 9) "a 8 9 b")) + (should (equal (format "a %08$s %0000000000000000009$s b" 1 2 3 4 5 6 7 8 9) + "a 8 9 b")) (should (equal (should-error (format "a %999999$s b" 11)) '(error "Not enough arguments for format string"))) + (should (equal (should-error (format "a %2147483647$s b")) + '(error "Not enough arguments for format string"))) + (should (equal (should-error (format "a %9223372036854775807$s b")) + '(error "Not enough arguments for format string"))) + (should (equal (should-error (format "a %9223372036854775808$s b")) + '(error "Not enough arguments for format string"))) + (should (equal (should-error (format "a %18446744073709551615$s b")) + '(error "Not enough arguments for format string"))) + (should (equal (should-error (format "a %18446744073709551616$s b")) + '(error "Not enough arguments for format string"))) + (should (equal (should-error + (format (format "a %%%d$d b" most-positive-fixnum))) + '(error "Not enough arguments for format string"))) + (should (equal (should-error + (format (format "a %%%d$d b" (+ 1.0 most-positive-fixnum)))) + '(error "Not enough arguments for format string"))) (should (equal (should-error (format "a %$s b" 11)) '(error "Invalid format operation %$"))) - (should (equal (should-error (format "a %0$s b" 11)) - '(error "Invalid format field number 0"))) - (should (equal (format "a %1$% %s b" 11) "a % 11 b"))) + (should (equal (should-error (format "a %-1$s b" 11)) + '(error "Invalid format operation %$")))) ;;; editfns-tests.el ends here commit 178d0cb5f530e6d7eb36eb9987ff405c854ccdb3 Author: Paul Eggert Date: Thu Jun 1 16:03:12 2017 -0700 Improve performance by avoiding strtoumax This made (string-to-number "10") 20% faster on my old desktop, an AMD Phenom II X4 910e running Fedora 25 x86-64. * admin/merge-gnulib (GNULIB_MODULES): Remove strtoumax. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/strtoul.c, lib/strtoull.c, lib/strtoumax.c, m4/strtoull.m4: * m4/strtoumax.m4: Remove. * src/editfns.c (str2num): New function. (styled_format): Use it instead of strtoumax. Use ptrdiff_t instead of uintmax_t. Check for integer overflow. * src/lread.c (LEAD_INT, DOT_CHAR, TRAIL_INT, E_EXP): Move to private scope and make them enums. (string_to_number): Compute integer value directly during first pass instead of revisiting it with strtoumax later. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 45e4a788a3..e5fb0f59fb 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -38,7 +38,7 @@ GNULIB_MODULES=' manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio - stpcpy strftime strtoimax strtoumax symlink sys_stat + stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index d23c2a57ec..73d304307d 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings MOSTLYCLEANFILES += core *.stackdump @@ -905,7 +905,6 @@ gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@ gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ gl_GNULIB_ENABLED_secure_getenv = @gl_GNULIB_ENABLED_secure_getenv@ gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ -gl_GNULIB_ENABLED_strtoull = @gl_GNULIB_ENABLED_strtoull@ gl_GNULIB_ENABLED_tempname = @gl_GNULIB_ENABLED_tempname@ gl_LIBOBJS = @gl_LIBOBJS@ gl_LTLIBOBJS = @gl_LTLIBOBJS@ @@ -2507,30 +2506,6 @@ EXTRA_libgnu_a_SOURCES += strtol.c strtoll.c endif ## end gnulib module strtoll -## begin gnulib module strtoull -ifeq (,$(OMIT_GNULIB_MODULE_strtoull)) - -ifneq (,$(gl_GNULIB_ENABLED_strtoull)) - -endif -EXTRA_DIST += strtol.c strtoul.c strtoull.c - -EXTRA_libgnu_a_SOURCES += strtol.c strtoul.c strtoull.c - -endif -## end gnulib module strtoull - -## begin gnulib module strtoumax -ifeq (,$(OMIT_GNULIB_MODULE_strtoumax)) - - -EXTRA_DIST += strtoimax.c strtoumax.c - -EXTRA_libgnu_a_SOURCES += strtoimax.c strtoumax.c - -endif -## end gnulib module strtoumax - ## begin gnulib module symlink ifeq (,$(OMIT_GNULIB_MODULE_symlink)) diff --git a/lib/strtoul.c b/lib/strtoul.c deleted file mode 100644 index c4974e069e..0000000000 --- a/lib/strtoul.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 1991, 1997, 2009-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program 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. - - This program 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 this program. If not, see . */ - -#define UNSIGNED 1 - -#include "strtol.c" diff --git a/lib/strtoull.c b/lib/strtoull.c deleted file mode 100644 index 51ae3acb03..0000000000 --- a/lib/strtoull.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Function to parse an 'unsigned long long int' from text. - Copyright (C) 1995-1997, 1999, 2009-2017 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@gnu.org. - - This program 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 any - later version. - - This program 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 this program. If not, see . */ - -#define QUAD 1 - -#include "strtoul.c" - -#ifdef _LIBC -strong_alias (__strtoull_internal, __strtouq_internal) -weak_alias (strtoull, strtouq) -#endif diff --git a/lib/strtoumax.c b/lib/strtoumax.c deleted file mode 100644 index dc395d626a..0000000000 --- a/lib/strtoumax.c +++ /dev/null @@ -1,2 +0,0 @@ -#define UNSIGNED 1 -#include "strtoimax.c" diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 3f196d4f1d..8f53a990e3 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -140,8 +140,6 @@ AC_DEFUN([gl_EARLY], # Code from module string: # Code from module strtoimax: # Code from module strtoll: - # Code from module strtoull: - # Code from module strtoumax: # Code from module symlink: # Code from module sys_select: # Code from module sys_stat: @@ -364,12 +362,6 @@ AC_DEFUN([gl_INIT], gl_PREREQ_STRTOIMAX fi gl_INTTYPES_MODULE_INDICATOR([strtoimax]) - gl_FUNC_STRTOUMAX - if test $HAVE_DECL_STRTOUMAX = 0 || test $REPLACE_STRTOUMAX = 1; then - AC_LIBOBJ([strtoumax]) - gl_PREREQ_STRTOUMAX - fi - gl_INTTYPES_MODULE_INDICATOR([strtoumax]) gl_FUNC_SYMLINK if test $HAVE_SYMLINK = 0 || test $REPLACE_SYMLINK = 1; then AC_LIBOBJ([symlink]) @@ -420,7 +412,6 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false gl_gnulib_enabled_secure_getenv=false gl_gnulib_enabled_strtoll=false - gl_gnulib_enabled_strtoull=false gl_gnulib_enabled_tempname=false gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b () @@ -569,18 +560,6 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_strtoll=true fi } - func_gl_gnulib_m4code_strtoull () - { - if ! $gl_gnulib_enabled_strtoull; then - gl_FUNC_STRTOULL - if test $HAVE_STRTOULL = 0; then - AC_LIBOBJ([strtoull]) - gl_PREREQ_STRTOULL - fi - gl_STDLIB_MODULE_INDICATOR([strtoull]) - gl_gnulib_enabled_strtoull=true - fi - } func_gl_gnulib_m4code_tempname () { if ! $gl_gnulib_enabled_tempname; then @@ -649,9 +628,6 @@ AC_DEFUN([gl_INIT], if { test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; } && test $ac_cv_type_long_long_int = yes; then func_gl_gnulib_m4code_strtoll fi - if { test $HAVE_DECL_STRTOUMAX = 0 || test $REPLACE_STRTOUMAX = 1; } && test $ac_cv_type_unsigned_long_long_int = yes; then - func_gl_gnulib_m4code_strtoull - fi if test $HAVE_TIMEGM = 0 || test $REPLACE_TIMEGM = 1; then func_gl_gnulib_m4code_5264294aa0a5557541b53c8c741f7f31 fi @@ -670,7 +646,6 @@ AC_DEFUN([gl_INIT], AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c]) AM_CONDITIONAL([gl_GNULIB_ENABLED_secure_getenv], [$gl_gnulib_enabled_secure_getenv]) AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) - AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull]) AM_CONDITIONAL([gl_GNULIB_ENABLED_tempname], [$gl_gnulib_enabled_tempname]) AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec]) # End of code from modules @@ -940,9 +915,6 @@ AC_DEFUN([gl_FILE_LIST], [ lib/strtoimax.c lib/strtol.c lib/strtoll.c - lib/strtoul.c - lib/strtoull.c - lib/strtoumax.c lib/symlink.c lib/sys_select.in.h lib/sys_stat.in.h @@ -1051,8 +1023,6 @@ AC_DEFUN([gl_FILE_LIST], [ m4/string_h.m4 m4/strtoimax.m4 m4/strtoll.m4 - m4/strtoull.m4 - m4/strtoumax.m4 m4/symlink.m4 m4/sys_select_h.m4 m4/sys_socket_h.m4 diff --git a/m4/strtoull.m4 b/m4/strtoull.m4 deleted file mode 100644 index c6b215072b..0000000000 --- a/m4/strtoull.m4 +++ /dev/null @@ -1,24 +0,0 @@ -# strtoull.m4 serial 7 -dnl Copyright (C) 2002, 2004, 2006, 2008-2017 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -AC_DEFUN([gl_FUNC_STRTOULL], -[ - AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) - dnl We don't need (and can't compile) the replacement strtoull - dnl unless the type 'unsigned long long int' exists. - AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) - if test "$ac_cv_type_unsigned_long_long_int" = yes; then - AC_CHECK_FUNCS([strtoull]) - if test $ac_cv_func_strtoull = no; then - HAVE_STRTOULL=0 - fi - fi -]) - -# Prerequisites of lib/strtoull.c. -AC_DEFUN([gl_PREREQ_STRTOULL], [ - : -]) diff --git a/m4/strtoumax.m4 b/m4/strtoumax.m4 deleted file mode 100644 index 43ef5b5abb..0000000000 --- a/m4/strtoumax.m4 +++ /dev/null @@ -1,28 +0,0 @@ -# strtoumax.m4 serial 12 -dnl Copyright (C) 2002-2004, 2006, 2009-2017 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -AC_DEFUN([gl_FUNC_STRTOUMAX], -[ - AC_REQUIRE([gl_INTTYPES_H_DEFAULTS]) - - dnl On OSF/1 5.1 with cc, this function is declared but not defined. - AC_CHECK_FUNCS_ONCE([strtoumax]) - AC_CHECK_DECLS_ONCE([strtoumax]) - if test "$ac_cv_have_decl_strtoumax" = yes; then - if test "$ac_cv_func_strtoumax" != yes; then - # HP-UX 11.11 has "#define strtoimax(...) ..." but no function. - REPLACE_STRTOUMAX=1 - fi - else - HAVE_DECL_STRTOUMAX=0 - fi -]) - -# Prerequisites of lib/strtoumax.c. -AC_DEFUN([gl_PREREQ_STRTOUMAX], [ - AC_CHECK_DECLS([strtoull]) - AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) -]) diff --git a/src/editfns.c b/src/editfns.c index 98187df5d9..1dbae8f5d4 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3851,6 +3851,23 @@ usage: (propertize STRING &rest PROPERTIES) */) return string; } +/* Convert the prefix of STR from ASCII decimal digits to a number. + Set *STR_END to the address of the first non-digit. Return the + number, or PTRDIFF_MAX on overflow. Return 0 if there is no number. + This is like strtol for ptrdiff_t and base 10 and C locale, + except without negative numbers or errno. */ + +static ptrdiff_t +str2num (char *str, char **str_end) +{ + ptrdiff_t n = 0; + for (; c_isdigit (*str); str++) + if (INT_MULTIPLY_WRAPV (n, 10, &n) || INT_ADD_WRAPV (n, *str - '0', &n)) + n = PTRDIFF_MAX; + *str_end = str; + return n; +} + DEFUN ("format", Fformat, Sformat, 1, MANY, 0, doc: /* Format a string out of a format-string and arguments. The first argument is a format control string. @@ -4057,17 +4074,16 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) digits to print after the '.' for floats, or the max. number of chars to print from a string. */ - uintmax_t num; + ptrdiff_t num; char *num_end; if (c_isdigit (*format)) { - num = strtoumax (format, &num_end, 10); + num = str2num (format, &num_end); if (*num_end == '$') { if (num == 0) error ("Invalid format field number 0"); - n = min (num, PTRDIFF_MAX); - n--; + n = num - 1; format = num_end + 1; } } @@ -4095,15 +4111,15 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) space_flag &= ! plus_flag; zero_flag &= ! minus_flag; - num = strtoumax (format, &num_end, 10); + num = str2num (format, &num_end); if (max_bufsize <= num) string_overflow (); ptrdiff_t field_width = num; bool precision_given = *num_end == '.'; - uintmax_t precision = (precision_given - ? strtoumax (num_end + 1, &num_end, 10) - : UINTMAX_MAX); + ptrdiff_t precision = (precision_given + ? str2num (num_end + 1, &num_end) + : PTRDIFF_MAX); format = num_end; if (format == end) @@ -4176,7 +4192,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) /* handle case (precision[n] >= 0) */ ptrdiff_t prec = -1; - if (precision_given && precision <= TYPE_MAXIMUM (ptrdiff_t)) + if (precision_given) prec = precision; /* lisp_string_width ignores a precision of 0, but GNU @@ -4424,8 +4440,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) padding and excess precision. Deal with excess precision first. This happens only when the format specifies ridiculously large precision. */ - uintmax_t excess_precision = precision - prec; - uintmax_t leading_zeros = 0, trailing_zeros = 0; + ptrdiff_t excess_precision + = precision_given ? precision - prec : 0; + ptrdiff_t leading_zeros = 0, trailing_zeros = 0; if (excess_precision) { if (float_conversion) @@ -4451,7 +4468,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) /* Compute the total bytes needed for this item, including excess precision and padding. */ - uintmax_t numwidth = sprintf_bytes + excess_precision; + ptrdiff_t numwidth; + if (INT_ADD_WRAPV (sprintf_bytes, excess_precision, &numwidth)) + numwidth = PTRDIFF_MAX; ptrdiff_t padding = numwidth < field_width ? field_width - numwidth : 0; if (max_bufsize - sprintf_bytes <= excess_precision diff --git a/src/lread.c b/src/lread.c index 368b86e818..f8493982c6 100644 --- a/src/lread.c +++ b/src/lread.c @@ -3495,25 +3495,18 @@ substitute_in_interval (INTERVAL interval, Lisp_Object arg) } -#define LEAD_INT 1 -#define DOT_CHAR 2 -#define TRAIL_INT 4 -#define E_EXP 16 - - -/* Convert STRING to a number, assuming base BASE. Return a fixnum if CP has - integer syntax and fits in a fixnum, else return the nearest float if CP has - either floating point or integer syntax and BASE is 10, else return nil. If - IGNORE_TRAILING, consider just the longest prefix of CP that has - valid floating point syntax. Signal an overflow if BASE is not 10 and the - number has integer syntax but does not fit. */ +/* Convert STRING to a number, assuming base BASE. Return a fixnum if + STRING has integer syntax and fits in a fixnum, else return the + nearest float if STRING has either floating point or integer syntax + and BASE is 10, else return nil. If IGNORE_TRAILING, consider just + the longest prefix of STRING that has valid floating point syntax. + Signal an overflow if BASE is not 10 and the number has integer + syntax but does not fit. */ Lisp_Object string_to_number (char const *string, int base, bool ignore_trailing) { - int state; char const *cp = string; - int leading_digit; bool float_syntax = 0; double value = 0; @@ -3525,15 +3518,23 @@ string_to_number (char const *string, int base, bool ignore_trailing) bool signedp = negative || *cp == '+'; cp += signedp; - state = 0; - - leading_digit = digit_to_number (*cp, base); + enum { INTOVERFLOW = 1, LEAD_INT = 2, DOT_CHAR = 4, TRAIL_INT = 8, + E_EXP = 16 }; + int state = 0; + int leading_digit = digit_to_number (*cp, base); + uintmax_t n = leading_digit; if (leading_digit >= 0) { state |= LEAD_INT; - do - ++cp; - while (digit_to_number (*cp, base) >= 0); + for (int digit; 0 <= (digit = digit_to_number (*++cp, base)); ) + { + if (INT_MULTIPLY_OVERFLOW (n, base)) + state |= INTOVERFLOW; + n *= base; + if (INT_ADD_OVERFLOW (n, digit)) + state |= INTOVERFLOW; + n += digit; + } } if (*cp == '.') { @@ -3583,32 +3584,22 @@ string_to_number (char const *string, int base, bool ignore_trailing) } float_syntax = ((state & (DOT_CHAR|TRAIL_INT)) == (DOT_CHAR|TRAIL_INT) - || state == (LEAD_INT|E_EXP)); + || (state & ~INTOVERFLOW) == (LEAD_INT|E_EXP)); } /* Return nil if the number uses invalid syntax. If IGNORE_TRAILING, accept any prefix that matches. Otherwise, the entire string must match. */ if (! (ignore_trailing ? ((state & LEAD_INT) != 0 || float_syntax) - : (!*cp && ((state & ~DOT_CHAR) == LEAD_INT || float_syntax)))) + : (!*cp && ((state & ~(INTOVERFLOW | DOT_CHAR)) == LEAD_INT + || float_syntax)))) return Qnil; /* If the number uses integer and not float syntax, and is in C-language range, use its value, preferably as a fixnum. */ if (leading_digit >= 0 && ! float_syntax) { - uintmax_t n; - - /* Fast special case for single-digit integers. This also avoids a - glitch when BASE is 16 and IGNORE_TRAILING, because in that - case some versions of strtoumax accept numbers like "0x1" that Emacs - does not allow. */ - if (digit_to_number (string[signedp + 1], base) < 0) - return make_number (negative ? -leading_digit : leading_digit); - - errno = 0; - n = strtoumax (string + signedp, NULL, base); - if (errno == ERANGE) + if (state & INTOVERFLOW) { /* Unfortunately there's no simple and accurate way to convert non-base-10 numbers that are out of C-language range. */ commit 53247108411a1e9d1aa5352c231fa049f3f918aa Author: Paul Eggert Date: Wed May 31 22:09:39 2017 -0700 Minor improvements to format field numbers * src/editfns.c (styled_format): Allow field numbers in a %% spec. No need for a special diagnostic for field numbers greater than PTRDIFF_MAX. Reword diagnostic for field 0. * test/src/editfns-tests.el (format-with-field): Adjust to match. diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 526b1fb4eb..4d33e55b01 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -864,15 +864,6 @@ below, as the first argument, and the string as the second, like this: (format "%s" @var{arbitrary-string}) @end example - If @var{string} contains more than one format specification and none -of the format specifications contain an explicit field number, the -format specifications correspond to successive values from -@var{objects}. Thus, the first format specification in @var{string} -uses the first such value, the second format specification uses the -second such value, and so on. Any extra format specifications (those -for which there are no corresponding values) cause an error. Any -extra values to be formatted are ignored. - Certain format specifications require values of particular types. If you supply a value that doesn't fit the requirements, an error is signaled. @@ -962,68 +953,33 @@ operation} error. @end group @end example + By default, format specifications correspond to successive values from +@var{objects}. Thus, the first format specification in @var{string} +uses the first such value, the second format specification uses the +second such value, and so on. Any extra format specifications (those +for which there are no corresponding values) cause an error. Any +extra values to be formatted are ignored. + @cindex field numbers in format spec - A specification can have a @dfn{field number}, which is a decimal -number after the initial @samp{%}, followed by a literal dollar sign -@samp{$}. If you provide a field number, then the argument to be -printed corresponds to the given field number instead of the next -argument. Field numbers start at 1. + A format specification can have a @dfn{field number}, which is a +decimal number immediately after the initial @samp{%}, followed by a +literal dollar sign @samp{$}. It causes the format specification to +convert the argument with the given number instead of the next +argument. Argument 1 is the argument just after the format. -You can mix specifications with and without field numbers. A + You can mix specifications with and without field numbers. A specification without a field number that follows a specification with a field number will convert the argument after the one specified by the field number: @example -(format "First argument %2$s, then %s, then %1$s" 1 2 3) - @result{} "First argument 2, then 3, then 1" -@end example - -You can't use field numbers in a @samp{%%} specification. - -@cindex field width -@cindex padding - A specification can have a @dfn{width}, which is a decimal number -between the @samp{%} and the specification character. If the printed -representation of the object contains fewer characters than this -width, @code{format} extends it with padding. The width specifier is -ignored for the @samp{%%} specification. Any padding introduced by -the width specifier normally consists of spaces inserted on the left: - -@example -(format "%5d is padded on the left with spaces" 123) - @result{} " 123 is padded on the left with spaces" -@end example - -@noindent -If the width is too small, @code{format} does not truncate the -object's printed representation. Thus, you can use a width to specify -a minimum spacing between columns with no risk of losing information. -In the following two examples, @samp{%7s} specifies a minimum width -of 7. In the first case, the string inserted in place of @samp{%7s} -has only 3 letters, and needs 4 blank spaces as padding. In the -second case, the string @code{"specification"} is 13 letters wide but -is not truncated. - -@example -@group -(format "The word '%7s' has %d letters in it." - "foo" (length "foo")) - @result{} "The word ' foo' has 3 letters in it." -(format "The word '%7s' has %d letters in it." - "specification" (length "specification")) - @result{} "The word 'specification' has 13 letters in it." -@end group +(format "Argument %2$s, then %s, then %1$s" "x" "y" "z") + @result{} "Argument y, then z, then x" @end example -If you want to use both a field number and a width, place the field -number before the width. For example, in @samp{%2$7s}, @samp{2} is -the field number and @samp{7} is the width. - @cindex flags in format specifications - After the @samp{%} and before the optional width specifier, you can -also put certain @dfn{flag characters}. The flag characters need to -come directly after a potential field number. + After the @samp{%} and any field number, you can put certain +@dfn{flag characters}. The flag @samp{+} inserts a plus sign before a positive number, so that it always has a sign. A space character as flag inserts a space @@ -1048,8 +1004,8 @@ specification characters like @samp{%s}, @samp{%S} and @samp{%c}. These specification characters accept the @samp{0} flag, but still pad with @emph{spaces}. - The flag @samp{-} causes the padding inserted by the width -specifier, if any, to be inserted on the right rather than the left. + The flag @samp{-} causes any padding inserted by the width, +if specified, to be inserted on the right rather than the left. If both @samp{-} and @samp{0} are present, the @samp{0} flag is ignored. @@ -1067,9 +1023,44 @@ ignored. @end group @end example +@cindex field width +@cindex padding + A specification can have a @dfn{width}, which is a decimal number +that appears after any field number and flags. If the printed +representation of the object contains fewer characters than this +width, @code{format} extends it with padding. The width is +ignored for the @samp{%%} specification. Any padding introduced by +the width normally consists of spaces inserted on the left: + +@example +(format "%5d is padded on the left with spaces" 123) + @result{} " 123 is padded on the left with spaces" +@end example + +@noindent +If the width is too small, @code{format} does not truncate the +object's printed representation. Thus, you can use a width to specify +a minimum spacing between columns with no risk of losing information. +In the following two examples, @samp{%7s} specifies a minimum width +of 7. In the first case, the string inserted in place of @samp{%7s} +has only 3 letters, and needs 4 blank spaces as padding. In the +second case, the string @code{"specification"} is 13 letters wide but +is not truncated. + +@example +@group +(format "The word '%7s' has %d letters in it." + "foo" (length "foo")) + @result{} "The word ' foo' has 3 letters in it." +(format "The word '%7s' has %d letters in it." + "specification" (length "specification")) + @result{} "The word 'specification' has 13 letters in it." +@end group +@end example + @cindex precision in format specifications All the specification characters allow an optional @dfn{precision} -before the character (after the width, if present). The precision is +after the field number, flags and width, if present. The precision is a decimal-point @samp{.} followed by a digit-string. For the floating-point specifications (@samp{%e} and @samp{%f}), the precision specifies how many digits following the decimal point to diff --git a/etc/NEWS b/etc/NEWS index 1b098f9842..7972511f7a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -369,7 +369,7 @@ libraries: 'find-library-other-window' and 'find-library-other-frame'. display of raw bytes from octal to hex. ** You can now provide explicit field numbers in format specifiers. -For example, '(format "%2$s %1$s" 1 2)' produces "2 1". +For example, '(format "%2$s %1$s" "X" "Y")' produces "Y X". * Editing Changes in Emacs 26.1 diff --git a/src/editfns.c b/src/editfns.c index 44341cef2d..98187df5d9 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -4046,9 +4046,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) field-width ::= [0-9]+ precision ::= '.' [0-9]* - If a field-number is specified, it specifies the argument - number to substitute. Otherwise, the next argument is - taken. + If present, a field-number specifies the argument number + to substitute. Otherwise, the next argument is taken. If a field-width is specified, it specifies to which width the output should be padded with blanks, if the output @@ -4058,28 +4057,20 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) digits to print after the '.' for floats, or the max. number of chars to print from a string. */ - char *field_end; - uintmax_t raw_field = strtoumax (format, &field_end, 10); - bool has_field = false; - if (c_isdigit (*format) && *field_end == '$') - { - if (raw_field < 1 || raw_field >= PTRDIFF_MAX) - { - /* doprnt doesn't support %.*s, so we need to copy - the field number string. */ - ptrdiff_t length = field_end - format; - eassert (length > 0); - eassert (length < PTRDIFF_MAX); - char *field = SAFE_ALLOCA (length + 1); - memcpy (field, format, length); - field[length] = '\0'; - error ("Invalid field number `%s'", field); - } - has_field = true; - /* n is incremented below. */ - n = raw_field - 1; - format = field_end + 1; - } + uintmax_t num; + char *num_end; + if (c_isdigit (*format)) + { + num = strtoumax (format, &num_end, 10); + if (*num_end == '$') + { + if (num == 0) + error ("Invalid format field number 0"); + n = min (num, PTRDIFF_MAX); + n--; + format = num_end + 1; + } + } bool minus_flag = false; bool plus_flag = false; @@ -4104,11 +4095,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) space_flag &= ! plus_flag; zero_flag &= ! minus_flag; - char *num_end; - uintmax_t raw_field_width = strtoumax (format, &num_end, 10); - if (max_bufsize <= raw_field_width) + num = strtoumax (format, &num_end, 10); + if (max_bufsize <= num) string_overflow (); - ptrdiff_t field_width = raw_field_width; + ptrdiff_t field_width = num; bool precision_given = *num_end == '.'; uintmax_t precision = (precision_given @@ -4123,13 +4113,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) memset (&discarded[format0 - format_start], 1, format - format0 - (conversion == '%')); if (conversion == '%') - { - if (has_field) - /* FIXME: `error' doesn't appear to support `%%'. */ - error ("Field number specified together with `%c' conversion", - '%'); - goto copy_char; - } + goto copy_char; ++n; if (! (n < nargs)) diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index f76c6c9fd3..c5923aaafb 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -186,13 +186,9 @@ (should (equal (should-error (format "a %999999$s b" 11)) '(error "Not enough arguments for format string"))) (should (equal (should-error (format "a %$s b" 11)) - ;; FIXME: there shouldn't be two % in the error - ;; string! - '(error "Invalid format operation %%$"))) + '(error "Invalid format operation %$"))) (should (equal (should-error (format "a %0$s b" 11)) - '(error "Invalid field number `0'"))) - (should (equal - (should-error (format "a %1$% %s b" 11)) - '(error "Field number specified together with `%' conversion")))) + '(error "Invalid format field number 0"))) + (should (equal (format "a %1$% %s b" 11) "a % 11 b"))) ;;; editfns-tests.el ends here commit 0dd1bbb0bb228acab21b8e16f2f2a0b5a17b19ab Author: Philipp Stephani Date: Thu Jun 1 00:09:43 2017 +0200 Implement field numbers in format strings A field number explicitly specifies the argument to be formatted. This is especially important for potential localization work, since grammars of various languages dictate different word orders. * src/editfns.c (Fformat): Update documentation. (styled_format): Implement field numbers. * doc/lispref/strings.texi (Formatting Strings): Document field numbers. * lisp/emacs-lisp/bytecomp.el (byte-compile-format-warn): Adapt. * test/src/editfns-tests.el (format-with-field): New unit test. diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 9436a96ead..526b1fb4eb 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -864,7 +864,8 @@ below, as the first argument, and the string as the second, like this: (format "%s" @var{arbitrary-string}) @end example - If @var{string} contains more than one format specification, the + If @var{string} contains more than one format specification and none +of the format specifications contain an explicit field number, the format specifications correspond to successive values from @var{objects}. Thus, the first format specification in @var{string} uses the first such value, the second format specification uses the @@ -961,6 +962,25 @@ operation} error. @end group @end example +@cindex field numbers in format spec + A specification can have a @dfn{field number}, which is a decimal +number after the initial @samp{%}, followed by a literal dollar sign +@samp{$}. If you provide a field number, then the argument to be +printed corresponds to the given field number instead of the next +argument. Field numbers start at 1. + +You can mix specifications with and without field numbers. A +specification without a field number that follows a specification with +a field number will convert the argument after the one specified by +the field number: + +@example +(format "First argument %2$s, then %s, then %1$s" 1 2 3) + @result{} "First argument 2, then 3, then 1" +@end example + +You can't use field numbers in a @samp{%%} specification. + @cindex field width @cindex padding A specification can have a @dfn{width}, which is a decimal number @@ -996,9 +1016,14 @@ is not truncated. @end group @end example +If you want to use both a field number and a width, place the field +number before the width. For example, in @samp{%2$7s}, @samp{2} is +the field number and @samp{7} is the width. + @cindex flags in format specifications - Immediately after the @samp{%} and before the optional width -specifier, you can also put certain @dfn{flag characters}. + After the @samp{%} and before the optional width specifier, you can +also put certain @dfn{flag characters}. The flag characters need to +come directly after a potential field number. The flag @samp{+} inserts a plus sign before a positive number, so that it always has a sign. A space character as flag inserts a space diff --git a/etc/NEWS b/etc/NEWS index 055de8ca9e..1b098f9842 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -368,6 +368,9 @@ libraries: 'find-library-other-window' and 'find-library-other-frame'. ** The new variable 'display-raw-bytes-as-hex' allows to change the display of raw bytes from octal to hex. +** You can now provide explicit field numbers in format specifiers. +For example, '(format "%2$s %1$s" 1 2)' produces "2 1". + * Editing Changes in Emacs 26.1 diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 12a7d4afc2..e5b9b47b1d 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1375,10 +1375,15 @@ extra args." (let ((nfields (with-temp-buffer (insert (nth 1 form)) (goto-char (point-min)) - (let ((n 0)) + (let ((i 0) (n 0)) (while (re-search-forward "%." nil t) - (unless (eq ?% (char-after (1+ (match-beginning 0)))) - (setq n (1+ n)))) + (backward-char) + (unless (eq ?% (char-after)) + (setq i (if (looking-at "\\([0-9]+\\)\\$") + (string-to-number (match-string 1) 10) + (1+ i)) + n (max n i))) + (forward-char)) n))) (nargs (- (length form) 2))) (unless (= nargs nfields) diff --git a/src/editfns.c b/src/editfns.c index 89a6724104..44341cef2d 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -48,6 +48,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include #include @@ -3856,7 +3857,7 @@ The first argument is a format control string. The other arguments are substituted into it to make the result, a string. The format control string may contain %-sequences meaning to substitute -the next available argument: +the next available argument, or the argument explicitly specified: %s means print a string argument. Actually, prints any object, with `princ'. %d means print as signed number in decimal. @@ -3873,13 +3874,17 @@ the next available argument: The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. Use %% to put a single % into the output. -A %-sequence may contain optional flag, width, and precision -specifiers, as follows: +A %-sequence may contain optional field number, flag, width, and +precision specifiers, as follows: - %character + %character -where flags is [+ #-0]+, width is [0-9]+, and precision is a literal -period "." followed by [0-9]+ +where field is [0-9]+ followed by a literal dollar "$", flags is +[+ #-0]+, width is [0-9]+, and precision is a literal period "." +followed by [0-9]+. + +If field is given, it must be a one-based argument number; the given +argument is substituted instead of the next one. The + flag character inserts a + before any positive number, while a space inserts a space before any positive number; these flags only @@ -4032,14 +4037,19 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) { /* General format specifications look like - '%' [flags] [field-width] [precision] format + '%' [field-number] [flags] [field-width] [precision] format where + field-number ::= [0-9]+ '$' flags ::= [-+0# ]+ field-width ::= [0-9]+ precision ::= '.' [0-9]* + If a field-number is specified, it specifies the argument + number to substitute. Otherwise, the next argument is + taken. + If a field-width is specified, it specifies to which width the output should be padded with blanks, if the output string is shorter than field-width. @@ -4048,6 +4058,29 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) digits to print after the '.' for floats, or the max. number of chars to print from a string. */ + char *field_end; + uintmax_t raw_field = strtoumax (format, &field_end, 10); + bool has_field = false; + if (c_isdigit (*format) && *field_end == '$') + { + if (raw_field < 1 || raw_field >= PTRDIFF_MAX) + { + /* doprnt doesn't support %.*s, so we need to copy + the field number string. */ + ptrdiff_t length = field_end - format; + eassert (length > 0); + eassert (length < PTRDIFF_MAX); + char *field = SAFE_ALLOCA (length + 1); + memcpy (field, format, length); + field[length] = '\0'; + error ("Invalid field number `%s'", field); + } + has_field = true; + /* n is incremented below. */ + n = raw_field - 1; + format = field_end + 1; + } + bool minus_flag = false; bool plus_flag = false; bool space_flag = false; @@ -4090,7 +4123,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) memset (&discarded[format0 - format_start], 1, format - format0 - (conversion == '%')); if (conversion == '%') - goto copy_char; + { + if (has_field) + /* FIXME: `error' doesn't appear to support `%%'. */ + error ("Field number specified together with `%c' conversion", + '%'); + goto copy_char; + } ++n; if (! (n < nargs)) diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 8019eb0383..f76c6c9fd3 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -177,4 +177,22 @@ (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" nil (concat (make-string 2048 ?X) "0"))))) +(ert-deftest format-with-field () + (should (equal (format "First argument %2$s, then %s, then %1$s" 1 2 3) + "First argument 2, then 3, then 1")) + (should (equal (format "a %2$s %d %1$d %2$S %d %d b" 11 "22" 33 44) + "a 22 33 11 \"22\" 33 44 b")) + (should (equal (format "a %08$s %s b" 1 2 3 4 5 6 7 8 9) "a 8 9 b")) + (should (equal (should-error (format "a %999999$s b" 11)) + '(error "Not enough arguments for format string"))) + (should (equal (should-error (format "a %$s b" 11)) + ;; FIXME: there shouldn't be two % in the error + ;; string! + '(error "Invalid format operation %%$"))) + (should (equal (should-error (format "a %0$s b" 11)) + '(error "Invalid field number `0'"))) + (should (equal + (should-error (format "a %1$% %s b" 11)) + '(error "Field number specified together with `%' conversion")))) + ;;; editfns-tests.el ends here commit 404273aeacba39833ae3a38ce6764cc7a636e9d9 Author: Alexander Gramiak Date: Mon May 29 13:43:23 2017 -0600 Limit scope of local overriding-terminal-local-map The function `binding' may call isearch-done, which globally sets overriding-terminal-local-map to nil (Bug#23007). * lisp/isearch.el (isearch-mouse-2): Don't bind overriding-terminal-local-map around the call to `binding'. diff --git a/lisp/isearch.el b/lisp/isearch.el index c34739d638..5f34dcadb5 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2036,9 +2036,9 @@ For a click in the echo area, invoke `isearch-yank-x-selection'. Otherwise invoke whatever the calling mouse-2 command sequence is bound to outside of Isearch." (interactive "e") - (let* ((w (posn-window (event-start click))) - (overriding-terminal-local-map nil) - (binding (key-binding (this-command-keys-vector) t))) + (let ((w (posn-window (event-start click))) + (binding (let ((overriding-terminal-local-map nil)) + (key-binding (this-command-keys-vector) t)))) (if (and (window-minibuffer-p w) (not (minibuffer-window-active-p w))) ; in echo area (isearch-yank-x-selection) commit 8c0f845b34ff3fc9622fa7a433d8272d94698c44 Author: Stephen Berman Date: Thu Jun 1 22:15:50 2017 +0200 Correct and isolate the todo-mode test environment This avoids having to set todo-mode variables globally in the test file and prevents any exisiting user todo-mode files from influencing the tests. * test/lisp/calendar/todo-mode-tests.el: (with-todo-test): New macro. (todo-test-todo-quit01, todo-test-todo-quit02) (todo-test-item-highlighting): Use it. diff --git a/test/lisp/calendar/todo-mode-tests.el b/test/lisp/calendar/todo-mode-tests.el index a0d5f01617..5e1a22b37b 100644 --- a/test/lisp/calendar/todo-mode-tests.el +++ b/test/lisp/calendar/todo-mode-tests.el @@ -22,11 +22,6 @@ ;;; Commentary: -;; FIXME: -;; In its current form this file changes global variables defined in -;; todo-mode.el, so to avoid problems, these tests should not be run -;; if todo-mode.el is already loaded. - ;;; Code: (require 'ert) @@ -47,12 +42,28 @@ todo-test-data-dir) "Todo Archive mode test file.") -;; (setq todo-directory-orig todo-directory) - -(setq todo-directory todo-test-data-dir) +(defmacro with-todo-test (&rest body) + "Set up an isolated todo-mode test environment." + `(let* ((todo-test-home (make-temp-file "todo-test-home-")) + (process-environment (cons (format "HOME=%s" todo-test-home) + process-environment)) + (todo-directory todo-test-data-dir) + (todo-default-todo-file (todo-short-file-name + (car (funcall todo-files-function))))) + ,@body)) + +;; (defun todo-test-show (num &optional archive) +;; "Display category NUM of test todo file. +;; With non-nil ARCHIVE argument, display test archive file category." +;; (let* ((file (if archive todo-test-archive-1 todo-test-file-1)) +;; (buf (find-file-noselect file))) +;; (set-buffer buf) +;; (if archive (todo-archive-mode) (todo-mode)) +;; (setq todo-category-number num) +;; (todo-category-select))) (defun todo-test-get-archive (num) - "Make buffer displaying archive category NUM current." + "Display category NUM of todo archive test file." (let ((archive-buf (find-file-noselect todo-test-archive-1))) (set-buffer archive-buf) (todo-archive-mode) @@ -71,58 +82,55 @@ corresponding todo-mode category current, if it exits, otherwise the current todo-mode category. Quitting todo-mode without an intermediate buffer switch should not make the archive buffer current again." - (todo-test-get-archive 2) - (let ((cat-name (todo-current-category))) - (todo-quit) - (should (todo-test-is-current-buffer todo-test-file-1)) - (should (equal (todo-current-category) cat-name)) - (todo-test-get-archive 1) - (setq cat-name (todo-current-category)) - (todo-quit) - (should (todo-test-is-current-buffer todo-test-file-1)) - (should (equal todo-category-number 1)) - (todo-forward-category) ; Category 2 in todo file now current. - (todo-test-get-archive 3) ; No corresponding category in todo file. - (setq cat-name (todo-current-category)) - (todo-quit) - (should (todo-test-is-current-buffer todo-test-file-1)) - (should (equal todo-category-number 2)) - (todo-quit) - (should-not (todo-test-is-current-buffer todo-test-archive-1)))) + (with-todo-test + (todo-test-get-archive 2) + (let ((cat-name (todo-current-category))) + (todo-quit) + (should (todo-test-is-current-buffer todo-test-file-1)) + (should (equal (todo-current-category) cat-name)) + (todo-test-get-archive 1) + (setq cat-name (todo-current-category)) + (todo-quit) + (should (todo-test-is-current-buffer todo-test-file-1)) + (should (equal todo-category-number 1)) + (todo-forward-category) ; Category 2 in todo file now current. + (todo-test-get-archive 3) ; No corresponding category in todo file. + (setq cat-name (todo-current-category)) + (todo-quit) + (should (todo-test-is-current-buffer todo-test-file-1)) + (should (equal todo-category-number 2)) + (todo-quit) + (should-not (todo-test-is-current-buffer todo-test-archive-1))))) (ert-deftest todo-test-todo-quit02 () ; bug#27121 "Test the behavior of todo-quit with todo and non-todo buffers. If the buffer made current by invoking todo-quit in a todo-mode buffer is buried by quit-window, the todo-mode buffer should not become current." - (todo-test-get-archive 2) - (todo-show) - (should (todo-test-is-current-buffer todo-test-file-1)) - (let ((dir (dired default-directory))) - (todo-show) - (todo-quit) - (should (equal (current-buffer) dir)) - (quit-window) - (should-not (todo-test-is-current-buffer todo-test-file-1)))) + (with-todo-test + (todo-show) + (should (todo-test-is-current-buffer todo-test-file-1)) + (let ((dir (dired default-directory))) + (todo-show) + (todo-quit) + (should (equal (current-buffer) dir)) + (quit-window) + (should-not (todo-test-is-current-buffer todo-test-file-1))))) (ert-deftest todo-test-item-highlighting () ; bug#27133 "Test whether `todo-toggle-item-highlighting' highlights whole item. In particular, all lines of a multiline item should be highlighted." - (todo-test-get-archive 2) - (todo-show) - (todo-jump-to-category nil "testcat1") ; For test rerun. - (todo-toggle-item-highlighting) - (let ((end (1- (todo-item-end))) - (beg (todo-item-start))) - (should (eq (get-char-property beg 'face) 'hl-line)) - (should (eq (get-char-property end 'face) 'hl-line)) - (should (> (count-lines beg end) 1)) - (should (eq (next-single-char-property-change beg 'face) (1+ end)))) - (todo-toggle-item-highlighting)) ; Turn off highlighting (for test rerun). - - -;; FIXME: must do this only after running all tests! -;; (setq todo-directory todo-directory-orig) + (with-todo-test + (todo-show) + (todo-jump-to-category nil "testcat1") ; For test rerun. + (todo-toggle-item-highlighting) + (let ((end (1- (todo-item-end))) + (beg (todo-item-start))) + (should (eq (get-char-property beg 'face) 'hl-line)) + (should (eq (get-char-property end 'face) 'hl-line)) + (should (> (count-lines beg end) 1)) + (should (eq (next-single-char-property-change beg 'face) (1+ end)))) + (todo-toggle-item-highlighting))) ; Turn off highlighting (for test rerun). (provide 'todo-mode-tests) ;;; todo-mode-tests.el ends here commit 6cd374085caa1c506555eef72535a47b91a4b4da Author: Alan Third Date: Tue May 30 19:48:17 2017 +0100 Fix build errors on macOS 10.6 (bug#27059) * src/nsfns.m (compute_tip_xy): Don't use CGRectContainsPoint. diff --git a/src/nsfns.m b/src/nsfns.m index 7bac2836fe..0c865070fb 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2752,16 +2752,19 @@ and GNUstep implementations ("distributor-specific release /* Find the screen that pt is on. */ for (screen in [NSScreen screens]) -#ifdef NS_IMPL_COCOA - if (CGRectContainsPoint ((CGRect)[screen frame], (CGPoint)pt)) -#else if (pt.x >= screen.frame.origin.x && pt.x < screen.frame.origin.x + screen.frame.size.width && pt.y >= screen.frame.origin.y && pt.y < screen.frame.origin.y + screen.frame.size.height) -#endif break; + /* We could use this instead of the if above: + + if (CGRectContainsPoint ([screen frame], pt)) + + which would be neater, but it causes problems building on old + versions of macOS and in GNUstep. */ + /* Ensure in bounds. (Note, screen origin = lower left.) */ if (INTEGERP (left) || INTEGERP (right)) *root_x = pt.x; commit 5dc0129c299f6cc7a0bdfbf7edc92a85bb3a0597 Author: Eli Zaretskii Date: Thu Jun 1 21:29:24 2017 +0300 Improve testing of octal and hex display of raw bytes * test/manual/redisplay-testsuite.el (test-redisplay-5-toggle) (test-redisplay-5): Add a test with a large codepoint. diff --git a/test/manual/redisplay-testsuite.el b/test/manual/redisplay-testsuite.el index 2175cbab1b..defc3fee32 100644 --- a/test/manual/redisplay-testsuite.el +++ b/test/manual/redisplay-testsuite.el @@ -294,30 +294,45 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (insert "\n")) -(defvar test-redisplay-5-expected-overlay nil) -(defvar test-redisplay-5-result-overlay nil) +(defvar test-redisplay-5a-expected-overlay nil) +(defvar test-redisplay-5a-result-overlay nil) +(defvar test-redisplay-5b-expected-overlay nil) +(defvar test-redisplay-5b-result-overlay nil) (defun test-redisplay-5-toggle (_event) (interactive "e") (setq display-raw-bytes-as-hex (not display-raw-bytes-as-hex)) (let ((label (if display-raw-bytes-as-hex "\\x80" "\\200"))) - (overlay-put test-redisplay-5-expected-overlay 'display + (overlay-put test-redisplay-5a-expected-overlay 'display + (propertize label 'face 'escape-glyph))) + (let ((label (if display-raw-bytes-as-hex "\\x3fffc" "\\777774"))) + (overlay-put test-redisplay-5b-expected-overlay 'display (propertize label 'face 'escape-glyph)))) (defun test-redisplay-5 () (insert "Test 5: Display of raw bytes:\n\n") (insert " Expected: ") - (setq test-redisplay-5-expected-overlay + (setq test-redisplay-5a-expected-overlay (test-insert-overlay " " 'display (propertize "\\200" 'face 'escape-glyph))) (insert "\n Result: ") - (setq test-redisplay-5-result-overlay + (setq test-redisplay-5a-result-overlay (test-insert-overlay " " 'display "\200")) (insert "\n\n") + (insert " Expected: ") + ;; This tests a large codepoint, to make sure the internal buffer we + ;; use to produce the representation is large enough. + (aset printable-chars #x3fffc nil) + (setq test-redisplay-5b-expected-overlay + (test-insert-overlay " " 'display + (propertize "\\777774" 'face 'escape-glyph))) + (insert "\n Result: ") + (setq test-redisplay-5b-result-overlay + (test-insert-overlay " " 'display (char-to-string #x3fffc))) + (insert "\n\n") (insert-button "Toggle between octal and hex display" 'action 'test-redisplay-5-toggle)) - (defun test-redisplay () (interactive) (let ((buf (get-buffer "*Redisplay Test*"))) commit cb9aa3515ac00826fd27ade7dfc829134ed38acc Author: Vasilij Schneidermann Date: Thu Jun 1 21:25:58 2017 +0300 Add customizable to display raw bytes as hex * src/xdisp.c (get_next_display_element): Dispatch used format string for unprintables based on new display-raw-bytes-as-hex variable. (display-raw-bytes-as-hex): New variable. (Bug#27122) * lisp/cus-start.el: Add defcustom form for display-raw-bytes-as-hex. * doc/emacs/display.texi: Document the new variable. * etc/NEWS: Mention display-raw-bytes-as-hex. * test/manual/redisplay-testsuite.el (test-redisplay-5-toggle) (test-redisplay-5): New tests. (test-redisplay): Call test-redisplay-5. diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index a0d0792eac..c4554eb318 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1763,3 +1763,9 @@ itself, in pixels; the default is 2. in text that is hard to read. Call the function @code{tty-suppress-bold-inverse-default-colors} with a non-@code{nil} argument to suppress the effect of bold-face in this case. + +@vindex display-raw-bytes-as-hex + Raw bytes are displayed in octal format by default, for example a +byte with a decimal value of 128 is displayed as @code{\200}. To +change display to the hexadecimal format of @code{\x80}, set the +variable @code{display-raw-bytes-as-hex} to @code{t}. diff --git a/etc/NEWS b/etc/NEWS index 43e7897120..055de8ca9e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -364,6 +364,10 @@ large integers from being displayed as characters. ** Two new commands for finding the source code of Emacs Lisp libraries: 'find-library-other-window' and 'find-library-other-frame'. ++++ +** The new variable 'display-raw-bytes-as-hex' allows to change the +display of raw bytes from octal to hex. + * Editing Changes in Emacs 26.1 diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 4253d40b75..744fe7f69e 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -583,6 +583,7 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Fit (t)" :value t) (const :tag "Grow only" :value grow-only)) "25.1") + (display-raw-bytes-as-hex display boolean "26.1") ;; xfaces.c (scalable-fonts-allowed display boolean "22.1") ;; xfns.c diff --git a/src/xdisp.c b/src/xdisp.c index eaa701e9cf..53210e5be5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -7055,7 +7055,7 @@ get_next_display_element (struct it *it) translated too. Non-printable characters and raw-byte characters are also - translated to octal form. */ + translated to octal or hexadecimal form. */ if (((c < ' ' || c == 127) /* ASCII control chars. */ ? (it->area != TEXT_AREA /* In mode line, treat \n, \t like other crl chars. */ @@ -7162,9 +7162,12 @@ get_next_display_element (struct it *it) int len, i; if (CHAR_BYTE8_P (c)) - /* Display \200 instead of \17777600. */ + /* Display \200 or \x80 instead of \17777600. */ c = CHAR_TO_BYTE8 (c); - len = sprintf (str, "%03o", c + 0u); + const char *format_string = display_raw_bytes_as_hex + ? "x%02x" + : "%03o"; + len = sprintf (str, format_string, c + 0u); XSETINT (it->ctl_chars[0], escape_glyph); for (i = 0; i < len; i++) @@ -32231,6 +32234,13 @@ display table takes effect; in this case, Emacs does not consult /* Initialize to t, since we need to disable reordering until loadup.el successfully loads charprop.el. */ redisplay__inhibit_bidi = true; + + DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex, + doc: /* Non-nil means display raw bytes in hexadecimal format. +The default is to use octal format (\200) whereas hexadecimal (\x80) +may be more familar to users. */); + display_raw_bytes_as_hex = false; + } diff --git a/test/manual/redisplay-testsuite.el b/test/manual/redisplay-testsuite.el index 694d55ab1d..2175cbab1b 100644 --- a/test/manual/redisplay-testsuite.el +++ b/test/manual/redisplay-testsuite.el @@ -34,7 +34,8 @@ (setq overlay (make-overlay opoint (point))) (while props (overlay-put overlay (car props) (cadr props)) - (setq props (cddr props))))) + (setq props (cddr props))) + overlay)) (defun test-redisplay-1 () (insert "Test 1: Displaying adjacent and overlapping overlays:\n\n") @@ -293,6 +294,29 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (insert "\n")) +(defvar test-redisplay-5-expected-overlay nil) +(defvar test-redisplay-5-result-overlay nil) + +(defun test-redisplay-5-toggle (_event) + (interactive "e") + (setq display-raw-bytes-as-hex (not display-raw-bytes-as-hex)) + (let ((label (if display-raw-bytes-as-hex "\\x80" "\\200"))) + (overlay-put test-redisplay-5-expected-overlay 'display + (propertize label 'face 'escape-glyph)))) + +(defun test-redisplay-5 () + (insert "Test 5: Display of raw bytes:\n\n") + (insert " Expected: ") + (setq test-redisplay-5-expected-overlay + (test-insert-overlay " " 'display + (propertize "\\200" 'face 'escape-glyph))) + (insert "\n Result: ") + (setq test-redisplay-5-result-overlay + (test-insert-overlay " " 'display "\200")) + (insert "\n\n") + (insert-button "Toggle between octal and hex display" + 'action 'test-redisplay-5-toggle)) + (defun test-redisplay () (interactive) @@ -309,5 +333,6 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (test-redisplay-2) (test-redisplay-3) (test-redisplay-4) + (test-redisplay-5) (goto-char (point-min)))) commit e5de79992a22f2932abb5f1f2600f576a60ae6ef Author: Eli Zaretskii Date: Thu Jun 1 21:24:15 2017 +0300 Revert "Add customizable to display raw bytes as hex" This reverts commit 7c9ac111c5e5d92e620b666893993d5dc562e483. diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index c4554eb318..a0d0792eac 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1763,9 +1763,3 @@ itself, in pixels; the default is 2. in text that is hard to read. Call the function @code{tty-suppress-bold-inverse-default-colors} with a non-@code{nil} argument to suppress the effect of bold-face in this case. - -@vindex display-raw-bytes-as-hex - Raw bytes are displayed in octal format by default, for example a -byte with a decimal value of 128 is displayed as @code{\200}. To -change display to the hexadecimal format of @code{\x80}, set the -variable @code{display-raw-bytes-as-hex} to @code{t}. diff --git a/etc/NEWS b/etc/NEWS index 055de8ca9e..43e7897120 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -364,10 +364,6 @@ large integers from being displayed as characters. ** Two new commands for finding the source code of Emacs Lisp libraries: 'find-library-other-window' and 'find-library-other-frame'. -+++ -** The new variable 'display-raw-bytes-as-hex' allows to change the -display of raw bytes from octal to hex. - * Editing Changes in Emacs 26.1 diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 744fe7f69e..4253d40b75 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -583,7 +583,6 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Fit (t)" :value t) (const :tag "Grow only" :value grow-only)) "25.1") - (display-raw-bytes-as-hex display boolean "26.1") ;; xfaces.c (scalable-fonts-allowed display boolean "22.1") ;; xfns.c diff --git a/src/xdisp.c b/src/xdisp.c index 53210e5be5..eaa701e9cf 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -7055,7 +7055,7 @@ get_next_display_element (struct it *it) translated too. Non-printable characters and raw-byte characters are also - translated to octal or hexadecimal form. */ + translated to octal form. */ if (((c < ' ' || c == 127) /* ASCII control chars. */ ? (it->area != TEXT_AREA /* In mode line, treat \n, \t like other crl chars. */ @@ -7162,12 +7162,9 @@ get_next_display_element (struct it *it) int len, i; if (CHAR_BYTE8_P (c)) - /* Display \200 or \x80 instead of \17777600. */ + /* Display \200 instead of \17777600. */ c = CHAR_TO_BYTE8 (c); - const char *format_string = display_raw_bytes_as_hex - ? "x%02x" - : "%03o"; - len = sprintf (str, format_string, c + 0u); + len = sprintf (str, "%03o", c + 0u); XSETINT (it->ctl_chars[0], escape_glyph); for (i = 0; i < len; i++) @@ -32234,13 +32231,6 @@ display table takes effect; in this case, Emacs does not consult /* Initialize to t, since we need to disable reordering until loadup.el successfully loads charprop.el. */ redisplay__inhibit_bidi = true; - - DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex, - doc: /* Non-nil means display raw bytes in hexadecimal format. -The default is to use octal format (\200) whereas hexadecimal (\x80) -may be more familar to users. */); - display_raw_bytes_as_hex = false; - } diff --git a/test/manual/redisplay-testsuite.el b/test/manual/redisplay-testsuite.el index 2175cbab1b..694d55ab1d 100644 --- a/test/manual/redisplay-testsuite.el +++ b/test/manual/redisplay-testsuite.el @@ -34,8 +34,7 @@ (setq overlay (make-overlay opoint (point))) (while props (overlay-put overlay (car props) (cadr props)) - (setq props (cddr props))) - overlay)) + (setq props (cddr props))))) (defun test-redisplay-1 () (insert "Test 1: Displaying adjacent and overlapping overlays:\n\n") @@ -294,29 +293,6 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (insert "\n")) -(defvar test-redisplay-5-expected-overlay nil) -(defvar test-redisplay-5-result-overlay nil) - -(defun test-redisplay-5-toggle (_event) - (interactive "e") - (setq display-raw-bytes-as-hex (not display-raw-bytes-as-hex)) - (let ((label (if display-raw-bytes-as-hex "\\x80" "\\200"))) - (overlay-put test-redisplay-5-expected-overlay 'display - (propertize label 'face 'escape-glyph)))) - -(defun test-redisplay-5 () - (insert "Test 5: Display of raw bytes:\n\n") - (insert " Expected: ") - (setq test-redisplay-5-expected-overlay - (test-insert-overlay " " 'display - (propertize "\\200" 'face 'escape-glyph))) - (insert "\n Result: ") - (setq test-redisplay-5-result-overlay - (test-insert-overlay " " 'display "\200")) - (insert "\n\n") - (insert-button "Toggle between octal and hex display" - 'action 'test-redisplay-5-toggle)) - (defun test-redisplay () (interactive) @@ -333,6 +309,5 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (test-redisplay-2) (test-redisplay-3) (test-redisplay-4) - (test-redisplay-5) (goto-char (point-min)))) commit 7c9ac111c5e5d92e620b666893993d5dc562e483 Author: Eli Zaretskii Date: Thu Jun 1 21:12:39 2017 +0300 Add customizable to display raw bytes as hex * src/xdisp.c (get_next_display_element): Dispatch used format string for unprintables based on new display-raw-bytes-as-hex variable. (display-raw-bytes-as-hex): New variable. (Bug#27122) * lisp/cus-start.el: Add defcustom form for display-raw-bytes-as-hex. * doc/emacs/display.texi: Document the new variable. * etc/NEWS: Mention display-raw-bytes-as-hex. * test/manual/redisplay-testsuite.el (test-redisplay-5-toggle) (test-redisplay-5): New tests. (test-redisplay): Call test-redisplay-5. diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index a0d0792eac..c4554eb318 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1763,3 +1763,9 @@ itself, in pixels; the default is 2. in text that is hard to read. Call the function @code{tty-suppress-bold-inverse-default-colors} with a non-@code{nil} argument to suppress the effect of bold-face in this case. + +@vindex display-raw-bytes-as-hex + Raw bytes are displayed in octal format by default, for example a +byte with a decimal value of 128 is displayed as @code{\200}. To +change display to the hexadecimal format of @code{\x80}, set the +variable @code{display-raw-bytes-as-hex} to @code{t}. diff --git a/etc/NEWS b/etc/NEWS index 43e7897120..055de8ca9e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -364,6 +364,10 @@ large integers from being displayed as characters. ** Two new commands for finding the source code of Emacs Lisp libraries: 'find-library-other-window' and 'find-library-other-frame'. ++++ +** The new variable 'display-raw-bytes-as-hex' allows to change the +display of raw bytes from octal to hex. + * Editing Changes in Emacs 26.1 diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 4253d40b75..744fe7f69e 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -583,6 +583,7 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Fit (t)" :value t) (const :tag "Grow only" :value grow-only)) "25.1") + (display-raw-bytes-as-hex display boolean "26.1") ;; xfaces.c (scalable-fonts-allowed display boolean "22.1") ;; xfns.c diff --git a/src/xdisp.c b/src/xdisp.c index eaa701e9cf..53210e5be5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -7055,7 +7055,7 @@ get_next_display_element (struct it *it) translated too. Non-printable characters and raw-byte characters are also - translated to octal form. */ + translated to octal or hexadecimal form. */ if (((c < ' ' || c == 127) /* ASCII control chars. */ ? (it->area != TEXT_AREA /* In mode line, treat \n, \t like other crl chars. */ @@ -7162,9 +7162,12 @@ get_next_display_element (struct it *it) int len, i; if (CHAR_BYTE8_P (c)) - /* Display \200 instead of \17777600. */ + /* Display \200 or \x80 instead of \17777600. */ c = CHAR_TO_BYTE8 (c); - len = sprintf (str, "%03o", c + 0u); + const char *format_string = display_raw_bytes_as_hex + ? "x%02x" + : "%03o"; + len = sprintf (str, format_string, c + 0u); XSETINT (it->ctl_chars[0], escape_glyph); for (i = 0; i < len; i++) @@ -32231,6 +32234,13 @@ display table takes effect; in this case, Emacs does not consult /* Initialize to t, since we need to disable reordering until loadup.el successfully loads charprop.el. */ redisplay__inhibit_bidi = true; + + DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex, + doc: /* Non-nil means display raw bytes in hexadecimal format. +The default is to use octal format (\200) whereas hexadecimal (\x80) +may be more familar to users. */); + display_raw_bytes_as_hex = false; + } diff --git a/test/manual/redisplay-testsuite.el b/test/manual/redisplay-testsuite.el index 694d55ab1d..2175cbab1b 100644 --- a/test/manual/redisplay-testsuite.el +++ b/test/manual/redisplay-testsuite.el @@ -34,7 +34,8 @@ (setq overlay (make-overlay opoint (point))) (while props (overlay-put overlay (car props) (cadr props)) - (setq props (cddr props))))) + (setq props (cddr props))) + overlay)) (defun test-redisplay-1 () (insert "Test 1: Displaying adjacent and overlapping overlays:\n\n") @@ -293,6 +294,29 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (insert "\n")) +(defvar test-redisplay-5-expected-overlay nil) +(defvar test-redisplay-5-result-overlay nil) + +(defun test-redisplay-5-toggle (_event) + (interactive "e") + (setq display-raw-bytes-as-hex (not display-raw-bytes-as-hex)) + (let ((label (if display-raw-bytes-as-hex "\\x80" "\\200"))) + (overlay-put test-redisplay-5-expected-overlay 'display + (propertize label 'face 'escape-glyph)))) + +(defun test-redisplay-5 () + (insert "Test 5: Display of raw bytes:\n\n") + (insert " Expected: ") + (setq test-redisplay-5-expected-overlay + (test-insert-overlay " " 'display + (propertize "\\200" 'face 'escape-glyph))) + (insert "\n Result: ") + (setq test-redisplay-5-result-overlay + (test-insert-overlay " " 'display "\200")) + (insert "\n\n") + (insert-button "Toggle between octal and hex display" + 'action 'test-redisplay-5-toggle)) + (defun test-redisplay () (interactive) @@ -309,5 +333,6 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff (test-redisplay-2) (test-redisplay-3) (test-redisplay-4) + (test-redisplay-5) (goto-char (point-min)))) commit e922e3c7a5c895f3875e7eb4670618891a4fd312 Author: Eli Zaretskii Date: Thu Jun 1 17:55:25 2017 +0300 Fix linum under text-scaling when leuven-theme is used * etc/themes/leuven-theme.el (linum): Make the 'linum' face inherit from 'default' and 'shadow', so that margins are enlarged as expected under text-scaling. diff --git a/etc/themes/leuven-theme.el b/etc/themes/leuven-theme.el index a633962fe7..c15bd41bf8 100644 --- a/etc/themes/leuven-theme.el +++ b/etc/themes/leuven-theme.el @@ -461,7 +461,7 @@ Semantic, and Ansi-Color faces are included -- and much more...") `(info-xref ((,class (:underline t :foreground "#006DAF")))) ; unvisited cross-references `(info-xref-visited ((,class (:underline t :foreground "magenta4")))) ; previously visited cross-references `(light-symbol-face ((,class (:background "#FFFFA0")))) - `(linum ((,class (:foreground "#9A9A9A" :background "#EDEDED")))) + `(linum ((,class (:inherit (default shadow) :foreground "#9A9A9A" :background "#EDEDED")))) `(log-view-file ((,class (:foreground "#0000CC" :background "#EAF2F5")))) `(lui-button-face ((,class ,link))) `(lui-highlight-face ((,class (:box '(:line-width 1 :color "#CC0000") :foreground "#CC0000" :background "#FFFF88")))) ; my nickname commit 9bc4c90d0731b309ca78eb65750da25e0b57b102 Author: Glenn Morris Date: Thu Jun 1 06:26:41 2017 -0400 ; Auto-commit of loaddefs files. diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index a5c6bc89d5..ae28ba93e6 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -1,4 +1,4 @@ -;;; loaddefs.tmp --- automatically extracted autoloads +;;; loaddefs.el --- automatically extracted autoloads ;; ;;; Code: @@ -4899,15 +4899,6 @@ printer proceeds to the next function on the list. This variable is not used at present, but it is defined in hopes that a future Emacs interpreter will be able to use it.") -(autoload 'cl-mapcar "cl-lib" "\ -Apply FUNCTION to each element of SEQ, and make a list of the results. -If there are several SEQs, FUNCTION is called with that many arguments, -and mapping stops as soon as the shortest list runs out. With just one -SEQ, this is like `mapcar'. With several, it is like the Common Lisp -`mapcar' function extended to arbitrary sequence types. - -\(fn FUNCTION SEQ...)" nil nil) - (defvar cl-old-struct-compat-mode nil "\ Non-nil if Cl-Old-Struct-Compat mode is enabled. See the `cl-old-struct-compat-mode' command @@ -5878,7 +5869,22 @@ with empty strings removed. ;;; Generated autoloads from textmodes/css-mode.el (autoload 'css-mode "css-mode" "\ -Major mode to edit Cascading Style Sheets. +Major mode to edit Cascading Style Sheets (CSS). +\\ +This mode provides syntax highlighting, indentation, completion, +and documentation lookup for CSS. + +Use `\\[complete-symbol]' to complete CSS properties, property values, +pseudo-elements, pseudo-classes, at-rules, bang-rules, and HTML +tags, classes and IDs. Completion candidates for HTML class +names and IDs are found by looking through open HTML mode +buffers. + +Use `\\[info-lookup-symbol]' to look up documentation of CSS properties, at-rules, +pseudo-classes, and pseudo-elements on the Mozilla Developer +Network (MDN). + +\\{css-mode-map} \(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.scss\\'" . scss-mode)) @@ -12721,12 +12727,24 @@ Visit the file you click on in another window. (autoload 'find-library "find-func" "\ Find the Emacs Lisp source of LIBRARY. -LIBRARY should be a string (the name of the library). If the -optional OTHER-WINDOW argument (i.e., the command argument) is -specified, pop to a different window before displaying the -buffer. -\(fn LIBRARY &optional OTHER-WINDOW)" t nil) +Interactively, prompt for LIBRARY using the one at or near point. + +\(fn LIBRARY)" t nil) + +(autoload 'find-library-other-window "find-func" "\ +Find the Emacs Lisp source of LIBRARY in another window. + +See `find-library' for more details. + +\(fn LIBRARY)" t nil) + +(autoload 'find-library-other-frame "find-func" "\ +Find the Emacs Lisp source of LIBRARY in another frame. + +See `find-library' for more details. + +\(fn LIBRARY)" t nil) (autoload 'find-function-search-for-symbol "find-func" "\ Search for SYMBOL's definition of type TYPE in LIBRARY. @@ -12887,7 +12905,7 @@ Define some key bindings for the find-function family of functions. \(fn)" nil nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-func" '("find-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-func" '("find-" "read-library-name"))) ;;;*** @@ -15889,6 +15907,14 @@ This discards the buffer's undo information. ;;;*** +;;;### (autoloads "actual autoloads are elsewhere" "hfy-cmap" "hfy-cmap.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from hfy-cmap.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "hfy-cmap" '("hfy-" "htmlfontify-unload-rgb-file"))) + +;;;*** + ;;;### (autoloads nil "hi-lock" "hi-lock.el" (0 0 0 0)) ;;; Generated autoloads from hi-lock.el @@ -21971,32 +21997,32 @@ QUALITY can be: ;;; Generated autoloads from net/net-utils.el (autoload 'ifconfig "net-utils" "\ -Run ifconfig and display diagnostic output. +Run `ifconfig-program' and display diagnostic output. \(fn)" t nil) (autoload 'iwconfig "net-utils" "\ -Run iwconfig and display diagnostic output. +Run `iwconfig-program' and display diagnostic output. \(fn)" t nil) (autoload 'netstat "net-utils" "\ -Run netstat and display diagnostic output. +Run `netstat-program' and display diagnostic output. \(fn)" t nil) (autoload 'arp "net-utils" "\ -Run arp and display diagnostic output. +Run `arp-program' and display diagnostic output. \(fn)" t nil) (autoload 'route "net-utils" "\ -Run route and display diagnostic output. +Run `route-program' and display diagnostic output. \(fn)" t nil) (autoload 'traceroute "net-utils" "\ -Run traceroute program for TARGET. +Run `traceroute-program' for TARGET. \(fn TARGET)" t nil) @@ -22008,32 +22034,49 @@ If your system's ping continues until interrupted, you can try setting \(fn HOST)" t nil) (autoload 'nslookup-host "net-utils" "\ -Lookup the DNS information for HOST. +Look up the DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. -\(fn HOST)" t nil) +This command uses `nslookup-program' for looking up the DNS information. + +\(fn HOST &optional NAME-SERVER)" t nil) (autoload 'nslookup "net-utils" "\ -Run nslookup program. +Run `nslookup-program'. \(fn)" t nil) (autoload 'dns-lookup-host "net-utils" "\ -Lookup the DNS information for HOST (name or IP address). +Look up the DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. -\(fn HOST)" t nil) +This command uses `dns-lookup-program' for looking up the DNS information. + +\(fn HOST &optional NAME-SERVER)" t nil) (autoload 'run-dig "net-utils" "\ -Run dig program. +Look up DNS information for HOST (name or IP address). +Optional argument NAME-SERVER says which server to use for +DNS resolution. +Interactively, prompt for NAME-SERVER if invoked with prefix argument. -\(fn HOST)" t nil) +This command uses `dig-program' for looking up the DNS information. + +\(fn HOST &optional NAME-SERVER)" t nil) (autoload 'ftp "net-utils" "\ -Run ftp program. +Run `ftp-program' to connect to HOST. \(fn HOST)" t nil) (autoload 'finger "net-utils" "\ Finger USER on HOST. +This command uses `finger-X.500-host-regexps' +and `network-connection-service-alist', which see. \(fn USER HOST)" t nil) @@ -22041,6 +22084,7 @@ Finger USER on HOST. Send SEARCH-STRING to server defined by the `whois-server-name' variable. If `whois-guess-server' is non-nil, then try to deduce the correct server from SEARCH-STRING. With argument, prompt for whois server. +The port is deduced from `network-connection-service-alist'. \(fn ARG SEARCH-STRING)" t nil) @@ -22051,6 +22095,7 @@ from SEARCH-STRING. With argument, prompt for whois server. (autoload 'network-connection-to-service "net-utils" "\ Open a network connection to SERVICE on HOST. +This command uses `network-connection-service-alist', which see. \(fn HOST SERVICE)" t nil) @@ -24195,13 +24240,13 @@ downloads in the background. (autoload 'package-install "package" "\ Install the package PKG. -PKG can be a package-desc or a symbol naming one of the available packages +PKG can be a `package-desc' or a symbol naming one of the available packages in an archive in `package-archives'. Interactively, prompt for its name. If called interactively or if DONT-SELECT nil, add PKG to `package-selected-packages'. -If PKG is a package-desc and it is already installed, don't try +If PKG is a `package-desc' and it is already installed, don't try to install it but still mark it as selected. \(fn PKG &optional DONT-SELECT)" t nil) @@ -24235,7 +24280,7 @@ If some packages are not installed propose to install them. (autoload 'package-reinstall "package" "\ Reinstall package PKG. -PKG should be either a symbol, the package name, or a package-desc +PKG should be either a symbol, the package name, or a `package-desc' object. \(fn PKG)" t nil) @@ -25024,6 +25069,31 @@ will not be shown. ;;;*** +;;;### (autoloads nil "pixel-scroll" "pixel-scroll.el" (0 0 0 0)) +;;; Generated autoloads from pixel-scroll.el + +(defvar pixel-scroll-mode nil "\ +Non-nil if Pixel-Scroll mode is enabled. +See the `pixel-scroll-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `pixel-scroll-mode'.") + +(custom-autoload 'pixel-scroll-mode "pixel-scroll" nil) + +(autoload 'pixel-scroll-mode "pixel-scroll" "\ +A minor mode to scroll text pixel-by-pixel. +With a prefix argument ARG, enable Pixel Scroll mode if ARG is positive, +and disable it otherwise. If called from Lisp, enable Pixel Scroll mode +if ARG is omitted or nil. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pixel-scroll" '("pixel-"))) + +;;;*** + ;;;### (autoloads nil "plstore" "plstore.el" (0 0 0 0)) ;;; Generated autoloads from plstore.el @@ -27460,7 +27530,7 @@ explicitly.") (make-obsolete-variable 'rmail-default-dont-reply-to-names 'mail-dont-reply-to-names "24.1") -(defvar rmail-ignored-headers (purecopy (concat "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^sender:" "\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:" "\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:" "\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:" "\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^face:" "\\|^x-mailer:\\|^delivered-to:\\|^lines:" "\\|^content-transfer-encoding:\\|^x-coding-system:" "\\|^return-path:\\|^errors-to:\\|^return-receipt-to:" "\\|^precedence:\\|^mime-version:" "\\|^list-owner:\\|^list-help:\\|^list-post:\\|^list-subscribe:" "\\|^list-id:\\|^list-unsubscribe:\\|^list-archive:" "\\|^content-length:\\|^nntp-posting-date:\\|^user-agent" "\\|^importance:\\|^envelope-to:\\|^delivery-date\\|^openpgp:" "\\|^mbox-line:\\|^cancel-lock:" "\\|^DomainKey-Signature:\\|^dkim-signature:" "\\|^resent-face:\\|^resent-x.*:\\|^resent-organization:\\|^resent-openpgp:" "\\|^x-.*:")) "\ +(defvar rmail-ignored-headers (purecopy (concat "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^sender:" "\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:" "\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:" "\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:" "\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^face:" "\\|^x-mailer:\\|^delivered-to:\\|^lines:" "\\|^content-transfer-encoding:\\|^x-coding-system:" "\\|^return-path:\\|^errors-to:\\|^return-receipt-to:" "\\|^precedence:\\|^mime-version:" "\\|^list-owner:\\|^list-help:\\|^list-post:\\|^list-subscribe:" "\\|^list-id:\\|^list-unsubscribe:\\|^list-archive:" "\\|^content-length:\\|^nntp-posting-date:\\|^user-agent" "\\|^importance:\\|^envelope-to:\\|^delivery-date\\|^openpgp:" "\\|^mbox-line:\\|^cancel-lock:" "\\|^DomainKey-Signature:\\|^dkim-signature:" "\\|^ARC-.*:" "\\|^Received-SPF:" "\\|^Authentication-Results:" "\\|^resent-face:\\|^resent-x.*:\\|^resent-organization:\\|^resent-openpgp:" "\\|^x-.*:")) "\ Regexp to match header fields that Rmail should normally hide. \(See also `rmail-nonignored-headers', which overrides this regexp.) This variable is used for reformatting the message header, @@ -29519,7 +29589,7 @@ Like `mail' command, but display mail buffer in another frame. ;;;### (autoloads nil "seq" "emacs-lisp/seq.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/seq.el -(push (purecopy '(seq 2 19)) package--builtin-versions) +(push (purecopy '(seq 2 20)) package--builtin-versions) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "seq" '("seq-"))) @@ -30178,6 +30248,23 @@ twice for the others. ;;;### (autoloads nil "smerge-mode" "vc/smerge-mode.el" (0 0 0 0)) ;;; Generated autoloads from vc/smerge-mode.el +(autoload 'smerge-refine-regions "smerge-mode" "\ +Show fine differences in the two regions BEG1..END1 and BEG2..END2. +PROPS-C is an alist of properties to put (via overlays) on the changes. +PROPS-R is an alist of properties to put on removed characters. +PROPS-A is an alist of properties to put on added characters. +If PROPS-R and PROPS-A are nil, put PROPS-C on all changes. +If PROPS-C is nil, but PROPS-R and PROPS-A are non-nil, +put PROPS-A on added characters, PROPS-R on removed characters. +If PROPS-C, PROPS-R and PROPS-A are non-nil, put PROPS-C on changed characters, +PROPS-A on added characters, and PROPS-R on removed characters. + +If non-nil, PREPROC is called with no argument in a buffer that contains +a copy of a region, just before preparing it to for `diff'. It can be +used to replace chars to try and eliminate some spurious differences. + +\(fn BEG1 END1 BEG2 END2 PROPS-C &optional PREPROC PROPS-R PROPS-A)" nil nil) + (autoload 'smerge-ediff "smerge-mode" "\ Invoke ediff to resolve the conflicts. NAME-UPPER, NAME-LOWER, and NAME-BASE, if non-nil, are used for the @@ -30312,7 +30399,7 @@ then `snmpv2-mode-hook'. ;;;### (autoloads nil "soap-client" "net/soap-client.el" (0 0 0 0)) ;;; Generated autoloads from net/soap-client.el -(push (purecopy '(soap-client 3 1 1)) package--builtin-versions) +(push (purecopy '(soap-client 3 1 2)) package--builtin-versions) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "soap-client" '("soap-"))) @@ -33976,20 +34063,17 @@ Used for file names matching `tramp-completion-file-name-regexp'. Operations not mentioned here will be handled by Tramp's file name handler functions, or the normal Emacs functions.") -(autoload 'tramp-file-name-handler "tramp" "\ -Invoke Tramp file name handler. -Falls back to normal file name handler if no Tramp file name handler exists. - -\(fn OPERATION &rest ARGS)" nil nil) - (autoload 'tramp-completion-file-name-handler "tramp" "\ Invoke Tramp file name completion handler. Falls back to normal file name handler if no Tramp file name handler exists. \(fn OPERATION &rest ARGS)" nil nil) +(defun tramp-autoload-file-name-handler (operation &rest args) "\ +Load Tramp file name handler, and perform OPERATION." (let ((default-directory temporary-file-directory)) (load "tramp" (quote noerror) (quote nomessage))) (apply operation args)) + (defun tramp-register-autoload-file-name-handlers nil "\ -Add Tramp file name handlers to `file-name-handler-alist' during autoload." (add-to-list (quote file-name-handler-alist) (cons tramp-initial-file-name-regexp (quote tramp-file-name-handler))) (put (quote tramp-file-name-handler) (quote safe-magic) t) (put (quote tramp-file-name-handler) (quote operations) (quote (file-name-all-completions file-name-completion file-remote-p))) (add-to-list (quote file-name-handler-alist) (cons tramp-initial-completion-file-name-regexp (quote tramp-completion-file-name-handler))) (put (quote tramp-completion-file-name-handler) (quote safe-magic) t) (put (quote tramp-completion-file-name-handler) (quote operations) (mapcar (quote car) tramp-completion-file-name-handler-alist))) +Add Tramp file name handlers to `file-name-handler-alist' during autoload." (add-to-list (quote file-name-handler-alist) (cons tramp-initial-file-name-regexp (quote tramp-autoload-file-name-handler))) (put (quote tramp-autoload-file-name-handler) (quote safe-magic) t) (add-to-list (quote file-name-handler-alist) (cons tramp-initial-completion-file-name-regexp (quote tramp-completion-file-name-handler))) (put (quote tramp-completion-file-name-handler) (quote safe-magic) t) (put (quote tramp-completion-file-name-handler) (quote operations) (mapcar (quote car) tramp-completion-file-name-handler-alist))) (tramp-register-autoload-file-name-handlers) @@ -34027,13 +34111,6 @@ Discard Tramp from loading remote files. ;;;### (autoloads nil "tramp-cmds" "net/tramp-cmds.el" (0 0 0 0)) ;;; Generated autoloads from net/tramp-cmds.el -(autoload 'tramp-change-syntax "tramp-cmds" "\ -Change Tramp syntax. -SYNTAX can be one of the symbols `default' (default), -`simplified' (ange-ftp like) or `separate' (XEmacs like). - -\(fn &optional SYNTAX)" t nil) - (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "tramp-cmds" '("tramp-"))) ;;;*** @@ -38161,9 +38238,9 @@ Zone out, completely. ;;;;;; "eshell/em-term.el" "eshell/em-tramp.el" "eshell/em-unix.el" ;;;;;; "eshell/em-xtra.el" "facemenu.el" "faces.el" "files.el" "font-core.el" ;;;;;; "font-lock.el" "format.el" "frame.el" "help.el" "hfy-cmap.el" -;;;;;; "htmlfontify-loaddefs.el" "ibuf-ext.el" "indent.el" "international/characters.el" -;;;;;; "international/charprop.el" "international/charscript.el" -;;;;;; "international/cp51932.el" "international/eucjp-ms.el" "international/mule-cmds.el" +;;;;;; "ibuf-ext.el" "indent.el" "international/characters.el" "international/charprop.el" +;;;;;; "international/charscript.el" "international/cp51932.el" +;;;;;; "international/eucjp-ms.el" "international/mule-cmds.el" ;;;;;; "international/mule-conf.el" "international/mule.el" "international/uni-bidi.el" ;;;;;; "international/uni-brackets.el" "international/uni-category.el" ;;;;;; "international/uni-combining.el" "international/uni-comment.el" @@ -38233,4 +38310,4 @@ Zone out, completely. ;; no-update-autoloads: t ;; coding: utf-8 ;; End: -;;; loaddefs.tmp ends here +;;; loaddefs.el ends here commit 877e808440d4bc2e62d6fb509defee91a3fdc895 Author: Paul Eggert Date: Wed May 31 22:38:04 2017 -0700 Free cwd when no longer needed * lib-src/emacsclient.c (main): Don’t dally when freeing cwd. diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 3a0715f137..8828b7652d 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -208,7 +208,7 @@ char *get_current_dir_name (void); /* Return the current working directory. Returns NULL on errors. Any other returned value must be freed with free. This is used only when get_current_dir_name is not defined on the system. */ -char* +char * get_current_dir_name (void) { char *buf; @@ -1702,6 +1702,7 @@ main (int argc, char **argv) if (tramp_prefix) quote_argument (emacs_socket, tramp_prefix); quote_argument (emacs_socket, cwd); + free (cwd); send_to_emacs (emacs_socket, "/"); send_to_emacs (emacs_socket, " "); @@ -1945,8 +1946,6 @@ main (int argc, char **argv) if (rl < 0) exit_status = EXIT_FAILURE; - free (cwd); /* Keep leak checkers happy. */ - CLOSE_SOCKET (emacs_socket); return exit_status; } commit c221f1466ed7e0f11f142d9cb3c0247b10e511c6 Author: Anders Waldenborg Date: Sun Apr 23 21:15:46 2017 +0200 Fix memory leak of cwd string in emacsclient (Bug#26628) * lib-src/emacsclient.c (main): emacsclient retrieves the current working directory using get_current_dir_name which returns a newly allocated string. Make sure this string is freed before exiting. Copyright-paperwork-exempt: yes diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index c21ee6bd39..3a0715f137 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -1945,6 +1945,8 @@ main (int argc, char **argv) if (rl < 0) exit_status = EXIT_FAILURE; + free (cwd); /* Keep leak checkers happy. */ + CLOSE_SOCKET (emacs_socket); return exit_status; } commit 28445aee59d54a8560aa4f33fa50f225b54317dc Author: Noam Postavsky Date: Wed May 10 23:27:37 2017 -0400 ; CONTRIBUTE: Better example for multi-entry example ChangeLog The new example has entries spanning multiple functions in a single file as well as multiple files. diff --git a/CONTRIBUTE b/CONTRIBUTE index 5fd197305b..3ed587c691 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -131,9 +131,12 @@ them right the first time, so here are guidelines for formatting them: - Preferred form for several entries with the same content: - * lisp/help.el (view-lossage): - * lisp/kmacro.el (kmacro-edit-lossage): - * lisp/edmacro.el (edit-kbd-macro): Fix docstring, lossage is now 300. + * lisp/menu-bar.el (clipboard-yank, clipboard-kill-ring-save) + (clipboard-kill-region): + * lisp/eshell/esh-io.el (eshell-virtual-targets) + (eshell-clipboard-append): + Replace option gui-select-enable-clipboard with + select-enable-clipboard; renamed October 2014. (Bug#25145) (Rather than anything involving "ditto" and suchlike.) commit afcbec61147fe84504de0d329ce40031fa79075b Author: Glenn Morris Date: Wed May 31 21:17:28 2017 -0400 Quieten compilation of some test files * test/lisp/dired-tests.el (dired-test-bug25609): Mark unused args. * test/src/data-tests.el (binding-test-set-constant-t) (binding-test-set-constant-nil, binding-test-set-constant-keyword) (binding-test-set-constant-nil): Silence compiler. * test/src/regex-tests.el (regex-tests-BOOST): Escape char literal. diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el index 1863864abd..1b814baac5 100644 --- a/test/lisp/dired-tests.el +++ b/test/lisp/dired-tests.el @@ -63,11 +63,11 @@ (dired-recursive-copies 'always)) ; Don't prompt me. (advice-add 'dired-query ; Don't ask confirmation to overwrite a file. :override - (lambda (sym prompt &rest args) (setq dired-query t)) + (lambda (_sym _prompt &rest _args) (setq dired-query t)) '((name . "advice-dired-query"))) (advice-add 'completing-read ; Just return init. :override - (lambda (prompt coll &optional pred match init hist def inherit keymap) + (lambda (_prompt _coll &optional _pred _match init _hist _def _inherit _keymap) init) '((name . "advice-completing-read"))) (dired to) diff --git a/test/src/data-tests.el b/test/src/data-tests.el index 8caafc11c2..00a30559e3 100644 --- a/test/src/data-tests.el +++ b/test/src/data-tests.el @@ -338,19 +338,19 @@ comparing the subr with a much slower lisp implementation." (ert-deftest binding-test-set-constant-t () "Test setting the constant t" - (should-error (setq t 'bob) :type 'setting-constant)) + (with-no-warnings (should-error (setq t 'bob) :type 'setting-constant))) (ert-deftest binding-test-set-constant-nil () "Test setting the constant nil" - (should-error (setq nil 'bob) :type 'setting-constant)) + (with-no-warnings (should-error (setq nil 'bob) :type 'setting-constant))) (ert-deftest binding-test-set-constant-keyword () "Test setting a keyword constant" - (should-error (setq :keyword 'bob) :type 'setting-constant)) + (with-no-warnings (should-error (setq :keyword 'bob) :type 'setting-constant))) (ert-deftest binding-test-set-constant-nil () "Test setting a keyword to itself" - (should (setq :keyword :keyword))) + (with-no-warnings (should (setq :keyword :keyword)))) ;; More tests to write - ;; kill-local-variable diff --git a/test/src/regex-tests.el b/test/src/regex-tests.el index db187fd4a6..1364bf6848 100644 --- a/test/src/regex-tests.el +++ b/test/src/regex-tests.el @@ -424,7 +424,7 @@ differences in behavior.") (let (failures basic icase notbol noteol) (regex-tests-generic-line - ?; "BOOST.tests" regex-tests-BOOST-whitelist + ?\; "BOOST.tests" regex-tests-BOOST-whitelist (if (save-excursion (re-search-forward "^-" nil t)) (setq basic (save-excursion (re-search-forward "REG_BASIC" nil t)) icase (save-excursion (re-search-forward "REG_ICASE" nil t)) commit 6aacd4fb09517b0dedf62333f0e27b28e8732f63 Author: Glenn Morris Date: Wed May 31 21:13:40 2017 -0400 Use true names for invocation- and source-directory * src/emacs.c (init_cmdargs) : * src/lread.c (init_lread) : Use true names. diff --git a/src/emacs.c b/src/emacs.c index 6ed16e8037..49ebb81767 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -463,6 +463,9 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd) if (!NILP (Vinvocation_directory)) { + if (NILP (Vpurify_flag) && !NILP (Ffboundp (Qfile_truename))) + Vinvocation_directory = call1 (Qfile_truename, Vinvocation_directory); + dir = Vinvocation_directory; #ifdef WINDOWSNT /* If we are running from the build directory, set DIR to the diff --git a/src/lread.c b/src/lread.c index 9e2168e7db..368b86e818 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4482,6 +4482,9 @@ load_path_default (void) void init_lread (void) { + if (NILP (Vpurify_flag) && !NILP (Ffboundp (Qfile_truename))) + Vsource_directory = call1 (Qfile_truename, Vsource_directory); + /* First, set Vload_path. */ /* Ignore EMACSLOADPATH when dumping. */ commit c4ecc01a45c6dd183f0ecf65e4c4c2c39beea278 Author: Glenn Morris Date: Wed May 31 21:11:47 2017 -0400 Avoid elisp-mode test failures when source dir has multiple names * test/lisp/progmodes/elisp-mode-tests.el (emacs-test-dir): Use the true name of the directory. diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el index 03ae8481ee..ee0837f2c4 100644 --- a/test/lisp/progmodes/elisp-mode-tests.el +++ b/test/lisp/progmodes/elisp-mode-tests.el @@ -290,7 +290,10 @@ to (xref-elisp-test-descr-to-target xref)." ;; `load-path' has the correct case, so this causes the expected test ;; values to have the wrong case). This is handled in ;; `xref-elisp-test-run'. -(defconst emacs-test-dir (downcase (file-name-directory (or load-file-name (buffer-file-name))))) +(defconst emacs-test-dir + (downcase + (file-truename (file-name-directory + (or load-file-name (buffer-file-name)))))) ;; alphabetical by test name commit 32fd8768093e21f1e812548d27c0bfd70cd82f78 Author: Paul Eggert Date: Wed May 31 16:50:08 2017 -0700 Fix bug with "%%" in error format * src/doprnt.c (doprnt): Format "%%" correctly. Problem reported by Philipp Stephani in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00901.html diff --git a/src/doprnt.c b/src/doprnt.c index bed9350f4a..418601acb0 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -438,7 +438,9 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, } case '%': - fmt--; /* Drop thru and this % will be treated as normal */ + /* Treat this '%' as normal. */ + fmt0 = fmt - 1; + break; } } commit 9c748b27c066b0cfdc8ff4a4e0fd545162836d06 Author: Paul Eggert Date: Wed May 31 16:22:24 2017 -0700 * src/editfns.c (Fmessage): Improve doc string (Bug#23425#130). diff --git a/src/editfns.c b/src/editfns.c index a51670cfdf..89a6724104 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3734,11 +3734,10 @@ In batch mode, the message is printed to the standard error stream, followed by a newline. The first argument is a format control string, and the rest are data -to be formatted under control of the string. See `format-message' for -details. - -Note: (message "%s" VALUE) displays the string VALUE without -interpreting format characters like `%', `\\=`', and `\\=''. +to be formatted under control of the string. Percent sign (%), grave +accent (\\=`) and apostrophe (\\=') are special in the format; see +`format-message' for details. To display STRING without special +treatment, use (message "%s" STRING). If the first argument is nil or the empty string, the function clears any existing message; this lets the minibuffer contents show. See commit 8130d910950a2b2a6f43903c980466f08edfd53c Author: Katsumi Yamaoka Date: Wed May 31 23:21:27 2017 +0000 Revert mml-generate-mime-1 (bug#27141) * lisp/gnus/mml.el (mml-generate-mime-1): Reverted to emacs-25 version with slight modernizations (bug#27141). diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 3a31349d37..ce28607a04 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -606,38 +606,28 @@ be \"related\" or \"alternate\"." (intern (downcase charset)))))) (if (and (not raw) (member (car (split-string type "/")) '("text" "message"))) - ;; We have a text-like MIME part, so we need to do - ;; charset encoding. (progn (with-temp-buffer - (set-buffer-multibyte nil) - ;; First insert the data into the buffer. - (if (and filename - (not (equal (cdr (assq 'nofile cont)) "yes"))) - (mm-insert-file-contents filename) - (insert - (with-temp-buffer - (cond - ((cdr (assq 'buffer cont)) - (insert-buffer-substring (cdr (assq 'buffer cont)))) - ((eq 'mml (car cont)) - (insert (cdr (assq 'contents cont)))) - (t - (insert (cdr (assq 'contents cont))) - ;; Remove quotes from quoted tags. - (goto-char (point-min)) - (while (re-search-forward - "<#!+/?\\(part\\|multipart\\|external\\|mml\\|secure\\)" - nil t) - (delete-region (+ (match-beginning 0) 2) - (+ (match-beginning 0) 3))))) - (setq charset - (mm-coding-system-to-mime-charset - (detect-coding-region - (point-min) (point-max) t))) - (encode-coding-region (point-min) (point-max) - charset) - (buffer-string)))) + (cond + ((cdr (assq 'buffer cont)) + (insert-buffer-substring (cdr (assq 'buffer cont)))) + ((and filename + (not (equal (cdr (assq 'nofile cont)) "yes"))) + (let ((coding-system-for-read coding)) + (mm-insert-file-contents filename))) + ((eq 'mml (car cont)) + (insert (cdr (assq 'contents cont)))) + (t + (save-restriction + (narrow-to-region (point) (point)) + (insert (cdr (assq 'contents cont))) + ;; Remove quotes from quoted tags. + (goto-char (point-min)) + (while (re-search-forward + "<#!+/?\\(part\\|multipart\\|external\\|mml\\|secure\\)" + nil t) + (delete-region (+ (match-beginning 0) 2) + (+ (match-beginning 0) 3)))))) (cond ((eq (car cont) 'mml) (let ((mml-boundary (mml-compute-boundary cont)) @@ -665,7 +655,7 @@ be \"related\" or \"alternate\"." ;; actually are hard newlines in the text. (let (use-hard-newlines) (when (and mml-enable-flowed - (string= type "text/plain") + (string= type "text/plain") (not (string= (cdr (assq 'sign cont)) "pgp")) (or (null (assq 'format cont)) (string= (cdr (assq 'format cont)) @@ -678,14 +668,13 @@ be \"related\" or \"alternate\"." ;; insert a "; format=flowed" string unless the ;; user has already specified it. (setq flowed (null (assq 'format cont))))) - (unless charset - (setq charset - ;; Prefer `utf-8' for text/calendar parts. - (if (string= type "text/calendar") - 'utf-8 - (mm-coding-system-to-mime-charset - (detect-coding-region - (point-min) (point-max) t))))) + ;; Prefer `utf-8' for text/calendar parts. + (if (or charset + (not (string= type "text/calendar"))) + (setq charset (mm-encode-body charset)) + (let ((mm-coding-system-priorities + (cons 'utf-8 mm-coding-system-priorities))) + (setq charset (mm-encode-body)))) (setq encoding (mm-body-encoding charset (cdr (assq 'encoding cont)))))) (setq coded (buffer-string))) @@ -696,26 +685,33 @@ be \"related\" or \"alternate\"." (set-buffer-multibyte nil) (cond ((cdr (assq 'buffer cont)) - (insert (string-as-unibyte - (with-current-buffer (cdr (assq 'buffer cont)) - (buffer-string))))) + ;; multibyte string that inserted to a unibyte buffer + ;; will be converted to the unibyte version safely. + (insert (with-current-buffer (cdr (assq 'buffer cont)) + (buffer-string)))) ((and filename (not (equal (cdr (assq 'nofile cont)) "yes"))) (let ((coding-system-for-read mm-binary-coding-system)) - (mm-insert-file-contents filename nil nil nil nil t))) + (mm-insert-file-contents filename nil nil nil nil t)) + (unless charset + (setq charset (mm-coding-system-to-mime-charset + (mm-find-buffer-file-coding-system + filename))))) (t (let ((contents (cdr (assq 'contents cont)))) - (if (multibyte-string-p contents) + (if (if (featurep 'xemacs) + (string-match "[^\000-\377]" contents) + (multibyte-string-p contents)) (progn - (mm-enable-multibyte) + (set-buffer-multibyte t) (insert contents) (unless raw (setq charset (mm-encode-body charset)))) (insert contents))))) (if (setq encoding (cdr (assq 'encoding cont))) (setq encoding (intern (downcase encoding)))) - (setq encoding (mm-encode-buffer type encoding) - coded (string-as-multibyte (buffer-string)))) + (setq encoding (mm-encode-buffer type encoding)) + (setq coded (decode-coding-string (buffer-string) 'us-ascii))) (mml-insert-mime-headers cont type charset encoding nil) (insert "\n" coded)))) ((eq (car cont) 'external) commit ca3622bf2eddc83783d44bb77d77ff60ba0e5611 Author: Michael Albinus Date: Wed May 31 20:32:31 2017 +0200 Fix Bug#27108 * lisp/recentf.el (recentf-load-list): Bind `non-essential', in order to avoid Tramp password requests during Emacs startup. (Bug#27108) diff --git a/lisp/recentf.el b/lisp/recentf.el index 4f0573911b..462ccb6db5 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -1304,7 +1304,9 @@ Read data from the file specified by `recentf-save-file'. When `recentf-initialize-file-name-history' is non-nil, initialize an empty `file-name-history' with the recent list." (interactive) - (let ((file (expand-file-name recentf-save-file))) + (let ((file (expand-file-name recentf-save-file)) + ;; We do not want Tramp asking for passwords. + (non-essential t)) (when (file-readable-p file) (load-file file) (and recentf-initialize-file-name-history commit 24ed64a04c62c8a9689396455af4670dcfc4fe49 Author: Glenn Morris Date: Wed May 31 12:56:40 2017 -0400 * test/Makefile.in (.SECONDARY): Stop make deleting .elc files. diff --git a/test/Makefile.in b/test/Makefile.in index 0d1663a4cd..4f12a8ea48 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -150,6 +150,9 @@ TESTS := $(LOGFILES:.log=) ## see what the problem was. .PRECIOUS: %.log +## Stop make deleting these as intermediate files. +.SECONDARY: ${ELFILES:.el=.elc} + .PHONY: ${TESTS} define test_template commit 76712f0febc5403eea38fe73cff199e9e6aba310 Author: Eli Zaretskii Date: Wed May 31 19:15:40 2017 +0300 Document current-line hscrolling in ELisp manual * doc/lispref/windows.texi (Horizontal Scrolling): Document the new mode of auto-hscrolling only the current line. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 3a9257e05a..d9b4b743a3 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -4249,6 +4249,13 @@ scrolling value explicitly. The value you specify serves as a lower bound for automatic scrolling, i.e., automatic scrolling will not scroll a window to a column less than the specified one. + The default value of @code{auto-hscroll-mode} is @code{t}; setting +it to @code{current-line} activates a variant of automatic horizontal +scrolling whereby only the line showing the cursor is horizontally +scrolled to make point visible, the rest of the window is left either +unscrolled, or at the minimum scroll amount set by @code{scroll-left} +and @code{scroll-right}, see below. + @deffn Command scroll-left &optional count set-minimum This function scrolls the selected window @var{count} columns to the left (or to the right if @var{count} is negative). The default commit 140ddc321be96c03ef234a12c56cef97a078fc07 Author: Eli Zaretskii Date: Wed May 31 19:01:31 2017 +0300 Support lower bound on hscrolling when only current line scrolls * doc/emacs/display.texi (Horizontal Scrolling): Document the new mode of auto-hscrolling only the current line. * src/xdisp.c (init_iterator): When hscrolling only the current line, apply the window's min_hscroll here, so that non-current lines will be hscrolled by that minimum. Suggested by Stephen Berman . (hscroll_window_tree): Account for window's min_hscroll when deciding whether to recompute the hscroll. (display_line): Subtract window's min_hscroll from x_incr, as that was already accounted for in init_iterator. (Bug#27008) diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index d07913cefb..a0d0792eac 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -308,7 +308,11 @@ displayed. When the text in a window is scrolled horizontally, text lines are truncated rather than continued (@pxref{Line Truncation}). If a window shows truncated lines, Emacs performs automatic horizontal scrolling whenever point moves off the left or right edge of the -screen. To disable automatic horizontal scrolling, set the variable +screen. By default, all the lines in the window are scrolled +horizontally together, but if you set the variable +@code{auto-hscroll-mode} to the special value of @code{current-line}, +only the line showing the cursor will be scrolled. To disable +automatic horizontal scrolling entirely, set the variable @code{auto-hscroll-mode} to @code{nil}. Note that when the automatic horizontal scrolling is turned off, if point moves off the edge of the screen, the cursor disappears to indicate that. (On text terminals, @@ -366,7 +370,10 @@ sufficiently large argument will restore the normal display. If you use those commands to scroll a window horizontally, that sets a lower bound for automatic horizontal scrolling. Automatic scrolling will continue to scroll the window, but never farther to the right -than the amount you previously set by @code{scroll-left}. +than the amount you previously set by @code{scroll-left}. When +@code{auto-hscroll-mode} is set to @code{current-line}, all the lines +other than the one showing the cursor will be scrolled by that minimal +amount. @node Narrowing @section Narrowing diff --git a/etc/NEWS b/etc/NEWS index 14cada4d4f..43e7897120 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -377,6 +377,7 @@ you may set this variable to nil. (Behind the scenes, there is now a new mode line construct, '%C', which operates exactly as '%c' does except that it counts from one.) ++++ ** New single-line horizontal scrolling mode. The 'auto-hscroll-mode' variable can now have a new special value, 'current-line', which causes only the line where the cursor is diff --git a/src/xdisp.c b/src/xdisp.c index f4461c1627..eaa701e9cf 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2890,8 +2890,19 @@ init_iterator (struct it *it, struct window *w, } else { + /* When hscrolling only the current line, don't apply the + hscroll here, it will be applied by display_line when it gets + to laying out the line showing point. However, if the + window's min_hscroll is positive, the user specified a lower + bound for automatic hscrolling, so they expect the + non-current lines to obey that hscroll amount. */ if (hscrolling_current_line_p (w)) - it->first_visible_x = 0; + { + if (w->min_hscroll > 0) + it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f); + else + it->first_visible_x = 0; + } else it->first_visible_x = window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f); @@ -13099,7 +13110,9 @@ hscroll_window_tree (Lisp_Object window) that doesn't need to be hscrolled. If we omit this condition, the line from which we move will remain hscrolled. */ - || (hscl && w->hscroll && !cursor_row->truncated_on_left_p))) + || (hscl + && w->hscroll != w->min_hscroll + && !cursor_row->truncated_on_left_p))) { struct it it; ptrdiff_t hscroll; @@ -20717,9 +20730,12 @@ display_line (struct it *it, int cursor_vpos) recenter_overlay_lists (current_buffer, IT_CHARPOS (*it)); /* If we are going to display the cursor's line, account for the - hscroll of that line. */ + hscroll of that line. We subtract the window's min_hscroll, + because that was already accounted for in init_iterator. */ if (hscroll_this_line) - x_incr = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f); + x_incr = + (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll) + * FRAME_COLUMN_WIDTH (it->f); /* Move over display elements that are not visible because we are hscrolled. This may stop at an x-position < first_visible_x commit a415c8bccb917c247792c4ce8e77b2512b3414d6 Author: Noam Postavsky Date: Sun May 28 17:01:05 2017 -0400 cl-print: handle circular objects when `print-circle' is nil (Bug#27117) * lisp/emacs-lisp/cl-print.el (cl-print--currently-printing): New variable. (cl-print-object): When `print-circle' is nil, bind it to a list of objects that are currently printing to avoid printing the same object endlessly. * test/lisp/emacs-lisp/cl-print-tests.el (cl-print-circle): New test. diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el index 65c86d2b65..70ccaac17b 100644 --- a/lisp/emacs-lisp/cl-print.el +++ b/lisp/emacs-lisp/cl-print.el @@ -37,6 +37,7 @@ "If non-nil, try and make sure the result can be `read'.") (defvar cl-print--number-table nil) +(defvar cl-print--currently-printing nil) ;;;###autoload (cl-defgeneric cl-print-object (object stream) @@ -59,8 +60,9 @@ call other entry points instead, such as `cl-prin1'." (princ "(" stream) (cl-print-object car stream) (while (and (consp object) - (not (and cl-print--number-table - (numberp (gethash object cl-print--number-table))))) + (not (if cl-print--number-table + (numberp (gethash object cl-print--number-table)) + (memq object cl-print--currently-printing)))) (princ " " stream) (cl-print-object (pop object) stream)) (when object @@ -156,15 +158,26 @@ call other entry points instead, such as `cl-prin1'." (cl-defmethod cl-print-object :around (object stream) ;; FIXME: Only put such an :around method on types where it's relevant. - (let ((n (if cl-print--number-table (gethash object cl-print--number-table)))) - (if (not (numberp n)) - (cl-call-next-method) - (if (> n 0) - ;; Already printed. Just print a reference. - (progn (princ "#" stream) (princ n stream) (princ "#" stream)) - (puthash object (- n) cl-print--number-table) - (princ "#" stream) (princ (- n) stream) (princ "=" stream) - (cl-call-next-method))))) + (cond + (print-circle + (let ((n (gethash object cl-print--number-table))) + (if (not (numberp n)) + (cl-call-next-method) + (if (> n 0) + ;; Already printed. Just print a reference. + (progn (princ "#" stream) (princ n stream) (princ "#" stream)) + (puthash object (- n) cl-print--number-table) + (princ "#" stream) (princ (- n) stream) (princ "=" stream) + (cl-call-next-method))))) + ((let ((already-printing (memq object cl-print--currently-printing))) + (when already-printing + ;; Currently printing, just print reference to avoid endless + ;; recursion. + (princ "#" stream) + (princ (length (cdr already-printing)) stream)))) + (t (let ((cl-print--currently-printing + (cons object cl-print--currently-printing))) + (cl-call-next-method))))) (defvar cl-print--number-index nil) diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el index 772601fe87..dfbe18d784 100644 --- a/test/lisp/emacs-lisp/cl-print-tests.el +++ b/test/lisp/emacs-lisp/cl-print-tests.el @@ -47,4 +47,12 @@ "\\`(#1=#s(foo 1 2 3) #1#)\\'" (cl-prin1-to-string (list x x))))))) +(ert-deftest cl-print-circle () + (let ((x '(#1=(a . #1#) #1#))) + (let ((print-circle nil)) + (should (string-match "\\`((a . #[0-9]) (a . #[0-9]))\\'" + (cl-prin1-to-string x)))) + (let ((print-circle t)) + (should (equal "(#1=(a . #1#) #1#)" (cl-prin1-to-string x)))))) + ;;; cl-print-tests.el ends here. commit 94306c8b0d61a53b19dcee18475ea8692b001f5d Author: Noam Postavsky Date: Tue May 30 23:31:18 2017 -0400 Further simplify test/Makefile, optionally load elc tests * test/Makefile.in: Use make's error ignoring feature instead of suppressing test errors with shell. Compile test files in the main make invocation instead of a recursive 'make' call. Optionally load .elc test files if TEST_LOAD_EL is set to something other than 'yes'. Remove obsolete commentary. diff --git a/test/Makefile.in b/test/Makefile.in index 8880ee2193..0d1663a4cd 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -81,6 +81,10 @@ GDB = # supported everywhere. TEST_LOCALE = C +# Whether to run tests from .el files in preference to .elc, we do +# this by default since it gives nicer stacktraces. +TEST_LOAD_EL ?= yes + # The actual Emacs command run in the targets below. # Prevent any setting of EMACSLOADPATH in user environment causing problems. emacs = EMACSLOADPATH= LC_ALL=$(TEST_LOCALE) \ @@ -91,26 +95,6 @@ emacs = EMACSLOADPATH= LC_ALL=$(TEST_LOCALE) \ all: check -%.elc: %.el - $(AM_V_ELC)$(emacs) -f batch-byte-compile $< - -## Ignore any test errors so we can continue to test other files. -## But compilation errors are always fatal. -WRITE_LOG = > $@ 2>&1 || { stat=ERROR; cat $@; }; echo $$stat: $@ - -## I'd prefer to use -emacs -f ert-run-tests-batch-and-exit rather -## than || true, since the former makes problems more obvious. -## I'd also prefer to @-hide the grep part and not the -## ert-run-tests-batch-and-exit part. -## -## We need to use $loadfile because: -## i) -L :$srcdir -l basename does not work, because we have files whose -## basename duplicates a file in lisp/ (eg eshell.el). -## ii) Although -l basename will automatically load .el or .elc, -## -l ./basename treats basename as a literal file (it would be nice -## to change this; bug#17848 - if that gets done, this can be simplified). -## -## Beware: it approximates 'no-byte-compile', so watch out for false-positives! SELECTOR_DEFAULT = (quote (not (tag :expensive-test))) SELECTOR_EXPENSIVE = nil ifdef SELECTOR @@ -127,16 +111,23 @@ else SELECTOR_ACTUAL=$(SELECTOR_EXPENSIVE) endif -## Byte-compile all test files to test for errors (unless explicitly -## told not to), but then evaluate the un-byte-compiled files, because -## they give cleaner stacktraces. +## Byte-compile all test files to test for errors. +%.elc: %.el + $(AM_V_ELC)$(emacs) -f batch-byte-compile $< + +## Save logs, and show logs for failed tests. +WRITE_LOG = > $@ 2>&1 || { STAT=$$?; cat $@; exit $$STAT; } + +ifeq ($(TEST_LOAD_EL), yes) +testloadfile = $*.el +else +testloadfile = $* +endif -## Beware: it approximates 'no-byte-compile', so watch out for false-positives! -%.log: %.el - $(AM_V_at)grep '^;.*no-byte-compile: t' $< > /dev/null || ${MAKE} $ Date: Wed May 31 12:05:06 2017 +0300 Avoid inflooping in redisplay due to Spacemacs and linum-mode * src/xdisp.c (redisplay_internal): Limit the number of redisplay retries when a frame becomes garbaged as result of redisplaying it. (Bug#27115) diff --git a/src/xdisp.c b/src/xdisp.c index c03689bf61..f4461c1627 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -13648,6 +13648,14 @@ redisplay_internal (void) enum { MAX_HSCROLL_RETRIES = 16 }; int hscroll_retries = 0; + /* Limit the number of retries for when frame(s) become garbaged as + result of redisplaying them. Some packages set various redisplay + hooks, such as window-scroll-functions, to run Lisp that always + calls APIs which cause the frame's garbaged flag to become set, + so we loop indefinitely. */ + enum {MAX_GARBAGED_FRAME_RETRIES = 2 }; + int garbaged_frame_retries = 0; + /* True means redisplay has to consider all windows on all frames. False, only selected_window is considered. */ bool consider_all_windows_p; @@ -14194,7 +14202,8 @@ redisplay_internal (void) garbage. We have to start over. These cases should be rare, so going all the way back to the top of redisplay should be good enough. */ - if (FRAME_GARBAGED_P (f)) + if (FRAME_GARBAGED_P (f) + && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES) goto retry; #if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS) commit a20c799653e875cfc916129fa1ff3e5402f6d6ec Author: Tino Calancha Date: Wed May 31 10:15:20 2017 +0900 * src/editfns.c (decode-time): Fix docstring. diff --git a/src/editfns.c b/src/editfns.c index 75eb75a729..a51670cfdf 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2139,7 +2139,7 @@ the epoch. The obsolete form (HIGH . LOW) is also still accepted. The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in the TZ environment variable. It can also be a list (as from -`current-time-zone') or an integer (as from `decode-time') applied +`current-time-zone') or an integer (the UTC offset in seconds) applied without consideration for daylight saving time. The list has the following nine members: SEC is an integer between 0 commit 5b4a95b7b26c21096737738b37d6ab78a19b4986 Author: Glenn Morris Date: Tue May 30 21:03:16 2017 -0400 * admin/update_autogen: Remove bzr support. diff --git a/admin/update_autogen b/admin/update_autogen index 9393ab0ee9..ba4ed00fa3 100755 --- a/admin/update_autogen +++ b/admin/update_autogen @@ -47,14 +47,7 @@ cd $PD cd ../ [ -d admin ] || die "Could not locate admin directory" -if [ -d .bzr ]; then - vcs=bzr -elif [ -e .git ]; then - vcs=git -else - die "Cannot determine vcs" -fi - +[ -d .git ] || die "No .git directory" usage () { @@ -157,10 +150,7 @@ OPTIND=1 ## Run status on inputs, list modified files on stdout. status () { - local statflag="-S" - [ "$vcs" = "git" ] && statflag="-s" - - $vcs status $statflag "$@" >| $tempfile || die "$vcs status error for $@" + git status -s "$@" >| $tempfile || die "git status error for $@" local stat file modified @@ -234,13 +224,11 @@ commit () echo "Committing..." - $vcs commit -m "; Auto-commit of $type files." "$@" || return $? + git commit -m "; Auto-commit of $type files." "$@" || return $? - [ "$vcs" = "git" ] && { - ## In case someone else pushed something while we were working. - $vcs pull --rebase || return $? - $vcs push || return $? - } + ## In case someone else pushed something while we were working. + git pull --rebase || return $? + git push || return $? echo "Committed files: $@" } # function commit commit 855b3e700fd1db62ae701a89bce4be5ed094352a Author: Glenn Morris Date: Tue May 30 21:01:56 2017 -0400 Avoid subr test failure when source dir has multiple names * test/lisp/subr-tests.el (subr-tests--this-file): Use the true name of the file. The following test does a string comparison of this value with that from method-files, which uses load-history, which contains true names. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 8fa258d12e..c0bfd40f80 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -298,7 +298,8 @@ cf. Bug#25477." (cl-defmethod subr-tests--generic ((x integer)) (message "%s is a number" x)) (cl-defgeneric subr-tests--generic-without-methods (x y)) -(defvar subr-tests--this-file (or load-file-name buffer-file-name)) +(defvar subr-tests--this-file + (file-truename (or load-file-name buffer-file-name))) (ert-deftest subr-tests--method-files--finds-methods () "`method-files' returns a list of files and methods for a generic function." commit e3b51b080fab02f579b7c6a91b609a2c0aca8339 Author: Dmitry Gutov Date: Wed May 31 01:29:34 2017 +0300 Extract eldoc--supported-p * lisp/emacs-lisp/eldoc.el (eldoc--supported-p): New function. (turn-on-eldoc-mode, eldoc-mode): Use it. (http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00865.html) diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index b0f6ea4412..40f5e2ef96 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -186,7 +186,7 @@ expression point is on." :group 'eldoc :lighter eldoc-minor-mode-string (setq eldoc-last-message nil) (cond - ((memq eldoc-documentation-function '(nil ignore)) + ((not (eldoc--supported-p)) (when (called-interactively-p 'any) (message "There is no ElDoc support in this buffer")) (setq eldoc-mode nil)) @@ -213,9 +213,12 @@ expression point is on." (defun turn-on-eldoc-mode () "Turn on `eldoc-mode' if the buffer has eldoc support enabled. See `eldoc-documentation-function' for more detail." - (unless (memq eldoc-documentation-function '(nil ignore)) + (when (eldoc--supported-p) (eldoc-mode 1))) +(defun eldoc--supported-p () + (not (memq eldoc-documentation-function '(nil ignore)))) + (defun eldoc-schedule-timer () (or (and eldoc-timer commit dd5b1c0d68a93d5bc6659c45a3f8f5028885edf8 Author: Glenn Morris Date: Tue May 30 14:16:35 2017 -0400 Make "make check" less verbose by default * test/Makefile.in (AM_DEFAULT_VERBOSITY, AM_V_ELC, am__v_ELC_) (am__v_ELC_0, am__v_ELC_1, AM_V_GEN, am__v_GEN_, am__v_GEN_0) (am__v_GEN_1, AM_V_at, am__v_at_, am__v_at_0, am__v_at_1): New, copied from lisp/Makefile.in. (%.elc, %.log): Simplify and quieten. diff --git a/test/Makefile.in b/test/Makefile.in index d13288b895..8880ee2193 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -38,6 +38,26 @@ MKDIR_P = @MKDIR_P@ SEPCHAR = @SEPCHAR@ + +# 'make' verbosity. +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ + +AM_V_ELC = $(am__v_ELC_@AM_V@) +am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@) +am__v_ELC_0 = @echo " ELC " $@; +am__v_ELC_1 = + +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = + +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = + + # We never change directory before running Emacs, so a relative file # name is fine, and makes life easier. If we need to change # directory, we can use emacs --chdir. @@ -72,8 +92,7 @@ emacs = EMACSLOADPATH= LC_ALL=$(TEST_LOCALE) \ all: check %.elc: %.el - @echo Compiling $< - @$(emacs) -f batch-byte-compile $< + $(AM_V_ELC)$(emacs) -f batch-byte-compile $< ## Ignore any test errors so we can continue to test other files. ## But compilation errors are always fatal. @@ -114,15 +133,10 @@ endif ## Beware: it approximates 'no-byte-compile', so watch out for false-positives! %.log: %.el - elc=$ /dev/null; then \ - ${MAKE} $$elc; \ - fi; \ - loadfile=$<; \ - echo Testing $$loadfile; \ - stat=OK ; \ - ${MKDIR_P} $(dir $@) ; \ - HOME=/nonexistent $(emacs) -l ert -l $$loadfile \ + $(AM_V_at)grep '^;.*no-byte-compile: t' $< > /dev/null || ${MAKE} $ Date: Tue May 30 17:42:52 2017 +0000 Mode line "%q" construct: Just use one number when both would be the same. * src/xdisp (decode_mode_spec): recode the "%q" bit appropriately. diff --git a/src/xdisp.c b/src/xdisp.c index ddb26b8def..c03689bf61 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23992,21 +23992,18 @@ decode_mode_spec (struct window *w, register int c, int field_width, ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos; ptrdiff_t begv = BUF_BEGV (b); ptrdiff_t zv = BUF_ZV (b); + int top_perc, bot_perc; if ((toppos <= begv) && (zv <= botpos)) return "All "; - if (toppos <= begv) - strcpy (decode_mode_spec_buf, "0-"); - else - sprintf (decode_mode_spec_buf, "%d-", - percent99 (toppos - begv, zv - begv)); + top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv); + bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv); - if (zv <= botpos) - strcat (decode_mode_spec_buf, "100%"); + if (top_perc == bot_perc) + sprintf (decode_mode_spec_buf, "%d%%", top_perc); else - sprintf (&decode_mode_spec_buf [strlen (decode_mode_spec_buf)], - "%d%%", percent99 (botpos - begv, zv - begv)); + sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc); return decode_mode_spec_buf; } commit 90e8d65118e1059ea6552c9e5eb59128af390200 Merge: caf9e31d71 a12c7ea88e Author: Alan Mackenzie Date: Tue May 30 17:39:40 2017 +0000 Merge branch 'master' of /home/acm/emacs/emacs.git/master commit a12c7ea88eb218550654fdb511d9be114742d692 Author: Alan Mackenzie Date: Tue May 30 17:07:12 2017 +0000 c-defun-name: Return fully qualified method names when wanted in C++, etc. * lisp/progmodes/cc-cmds.el (c-defun-name): Use c-back-over-compound-identifier in place of c-backward-token-2 near the end of the function. diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index a5ddcb4b92..9c0798e752 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -1870,7 +1870,7 @@ with a brace block." (c-backward-token-2) (c-backward-syntactic-ws)) (setq name-end (point)) - (c-backward-token-2) + (c-back-over-compound-identifier) (buffer-substring-no-properties (point) name-end))))))))) (defun c-declaration-limits (near) commit d17aa3e535bba5e93ff188d5460c91001074255e Author: Glenn Morris Date: Tue May 30 12:50:54 2017 -0400 Reduce scope of recent test/Makefile HOME change * test/Makefile.in (%.log): Move setting of HOME here from top-level. diff --git a/test/Makefile.in b/test/Makefile.in index 49a4dfdfd8..d13288b895 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -53,9 +53,6 @@ EMACSOPT = -batch --no-site-file --no-site-lisp -L "$(SEPCHAR)$(srcdir)" $(EMACS # Prevent any settings in the user environment causing problems. unexport EMACSDATA EMACSDOC EMACSPATH GREP_OPTIONS -# Prevent tests using or changing anything in HOME. -export HOME = /nonexistent - ## To run tests under a debugger, set this to eg: "gdb --args". GDB = @@ -125,7 +122,7 @@ endif echo Testing $$loadfile; \ stat=OK ; \ ${MKDIR_P} $(dir $@) ; \ - $(emacs) -l ert -l $$loadfile \ + HOME=/nonexistent $(emacs) -l ert -l $$loadfile \ --eval "(ert-run-tests-batch-and-exit ${SELECTOR_ACTUAL})" ${WRITE_LOG} ifeq (@HAVE_MODULES@, yes) commit 1b01601d3f5d34a267c47e5d1208aa01730dd157 Author: Paul Eggert Date: Tue May 30 09:27:33 2017 -0700 Skip .#* temporaries when finding sources Without this patch, ‘make check’ can fail with the diagnostic ‘invalid syntax in conditional’ if there is an Emacs temporary file whose name starts with ‘.#’, because the ‘#’ is treated as the start of a Make comment. * lisp/Makefile.in (loaddefs, tagsfiles, check-defun-deps): * test/Makefile.in (ELFILES): Skip files starting with ‘.’, so that the .#* files do not cause trouble. (We cannot easily skip just files starting with ‘.#’, since ‘#’ starts a Make comment!) diff --git a/lisp/Makefile.in b/lisp/Makefile.in index ba4925fb79..653200577d 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in @@ -78,7 +78,7 @@ LOADDEFS = $(lisp)/calendar/cal-loaddefs.el \ $(lisp)/net/tramp-loaddefs.el # All generated autoload files. -loaddefs = $(shell find ${srcdir} -name '*loaddefs.el') +loaddefs = $(shell find ${srcdir} -name '*loaddefs.el' ! -name '.*') # Elisp files auto-generated. AUTOGENEL = ${loaddefs} ${srcdir}/cus-load.el ${srcdir}/finder-inf.el \ ${srcdir}/subdirs.el ${srcdir}/eshell/esh-groups.el @@ -243,8 +243,8 @@ update-gnus-news: FORCE: .PHONY: FORCE -tagsfiles = $(shell find ${srcdir} -name '*.el') -tagsfiles := $(filter-out ${srcdir}/%loaddefs.el,${tagsfiles}) +tagsfiles = $(shell find ${srcdir} -name '*.el' \ + ! -name '.*' ! -name '*loaddefs.el') tagsfiles := $(filter-out ${srcdir}/ldefs-boot.el,${tagsfiles}) tagsfiles := $(filter-out ${srcdir}/eshell/esh-groups.el,${tagsfiles}) @@ -470,7 +470,7 @@ check-declare: ## This finds a lot of duplicates between foo.el and obsolete/foo.el. check-defun-dups: sed -n -e '/^(defun /s/\(.\)(.*/\1/p' \ - $$(find . -name '*.el' -print | \ + $$(find . -name '*.el' ! -name '.*' -print | \ grep -Ev '(loaddefs|ldefs-boot)\.el|obsolete') | sort | uniq -d # Dependencies diff --git a/test/Makefile.in b/test/Makefile.in index c9065d90d1..49a4dfdfd8 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -138,7 +138,7 @@ ELFILES := $(shell find ${srcdir} -path "${srcdir}/manual" -prune -o \ -path "${srcdir}/data" -prune -o \ -name "*resources" -prune -o \ ${maybe_exclude_module_tests} \ - -name "*.el" -print) + -name "*.el" ! -name ".*" -print) ## .log files may be in a different directory for out of source builds LOGFILES := $(patsubst %.el,%.log, \ $(patsubst $(srcdir)/%,%,$(ELFILES))) commit caf9e31d714dc817118e2549557fdda3d28a4c2b Merge: aeaef62cfd 91a52e38e5 Author: Alan Mackenzie Date: Tue May 30 16:27:36 2017 +0000 Merge branch 'master' of /home/acm/emacs/emacs.git/master commit 91a52e38e5194f19f0d44ae4c2ad88565b28a196 Author: Alan Mackenzie Date: Tue May 30 16:21:31 2017 +0000 Fix the mouse help/key map on the "%p" part of the mode line. * lisp/bindings.el (mode-line-percent-position): give it a `risky-local-variable' property. (mode-line-position): correct the quoting on the mode-line-percent-position part of the variable, allowing the properties to be properly recognized. diff --git a/lisp/bindings.el b/lisp/bindings.el index 0e6ffc275e..0994b7126d 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -382,14 +382,15 @@ displayed in `mode-line-position', a component of the default (6 "%q"))) :version "26.1" :group 'mode-line) +(put 'mode-line-percent-position 'risky-local-variable t) (defvar mode-line-position `((:propertize mode-line-percent-position - 'local-map mode-line-column-line-number-mode-map - 'mouse-face 'mode-line-highlight + local-map ,mode-line-column-line-number-mode-map + mouse-face mode-line-highlight ;; XXX needs better description - 'help-echo "Size indication mode\n\ + help-echo "Size indication mode\n\ mouse-1: Display Line and Column Mode Menu") (size-indication-mode (8 ,(propertize commit aeaef62cfd8e9b0d36e4125322e926e48ab9091a Author: Alan Mackenzie Date: Tue May 30 16:21:31 2017 +0000 Fix the mouse help/key map on the "%p" part of the mode line. * lisp/bindings.el (mode-line-percent-position): give it a `risky-local-variable' property. (mode-line-position): correct the quoting on the mode-line-percent-position part of the variable, allowing the properties to be properly recognized. diff --git a/lisp/bindings.el b/lisp/bindings.el index 0e6ffc275e..0994b7126d 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -382,14 +382,15 @@ displayed in `mode-line-position', a component of the default (6 "%q"))) :version "26.1" :group 'mode-line) +(put 'mode-line-percent-position 'risky-local-variable t) (defvar mode-line-position `((:propertize mode-line-percent-position - 'local-map mode-line-column-line-number-mode-map - 'mouse-face 'mode-line-highlight + local-map ,mode-line-column-line-number-mode-map + mouse-face mode-line-highlight ;; XXX needs better description - 'help-echo "Size indication mode\n\ + help-echo "Size indication mode\n\ mouse-1: Display Line and Column Mode Menu") (size-indication-mode (8 ,(propertize commit ebcc70ab1be968a9d98eaa7cf6a51421ff8ea62f Author: Paul Eggert Date: Tue May 30 09:15:05 2017 -0700 Merge from gnulib * build-aux/config.guess: Copy from gnulib. * lib/gnulib.mk.in: Regenerate. diff --git a/build-aux/config.guess b/build-aux/config.guess index faa63aa942..2193702b12 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -2,7 +2,7 @@ # Attempt to guess a canonical system name. # Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2017-05-11' +timestamp='2017-05-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -1304,14 +1304,21 @@ EOF if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 6d85dc5958..d23c2a57ec 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -645,6 +645,8 @@ NS_OBJ = @NS_OBJ@ NS_OBJC_OBJ = @NS_OBJC_OBJ@ NTDIR = @NTDIR@ NTLIB = @NTLIB@ +OBJC = @OBJC@ +OBJCFLAGS = @OBJCFLAGS@ OBJEXT = @OBJEXT@ OTHER_FILES = @OTHER_FILES@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ @@ -863,6 +865,7 @@ XRANDR_LIBS = @XRANDR_LIBS@ XWIDGETS_OBJ = @XWIDGETS_OBJ@ X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@ ac_ct_CC = @ac_ct_CC@ +ac_ct_OBJC = @ac_ct_OBJC@ archlibdir = @archlibdir@ bindir = @bindir@ bitmapdir = @bitmapdir@ commit 412c38aa28dd7e8363b481a09d1df62c40f9a5b7 Author: Glenn Morris Date: Tue May 30 08:39:39 2017 -0700 Stop make check interacting with HOME * test/Makefile.in (HOME): Export a non-existent value. diff --git a/test/Makefile.in b/test/Makefile.in index 4029bb2431..c9065d90d1 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -53,6 +53,9 @@ EMACSOPT = -batch --no-site-file --no-site-lisp -L "$(SEPCHAR)$(srcdir)" $(EMACS # Prevent any settings in the user environment causing problems. unexport EMACSDATA EMACSDOC EMACSPATH GREP_OPTIONS +# Prevent tests using or changing anything in HOME. +export HOME = /nonexistent + ## To run tests under a debugger, set this to eg: "gdb --args". GDB = commit a47dfec82e363257a00f5666845ebaa8d697ae42 Author: Paul Eggert Date: Tue May 30 08:28:54 2017 -0700 ; Spelling fixes for "SpamAssassin" diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi index a113272e49..3aa04caf86 100644 --- a/doc/misc/mh-e.texi +++ b/doc/misc/mh-e.texi @@ -7644,10 +7644,10 @@ Whitelisted message face @end vtable @cindex SpamProbe -@cindex Spamassassin +@cindex SpamAssassin @cindex bogofilter @cindex spam filters, SpamProbe -@cindex spam filters, Spamassassin +@cindex spam filters, SpamAssassin @cindex spam filters, bogofilter MH-E depends on @uref{http://spamassassin.apache.org/, SpamAssassin}, @@ -7720,8 +7720,8 @@ MH-E can work with. @subheading SpamAssassin -@cindex Spamassassin -@cindex spam filters, Spamassassin +@cindex SpamAssassin +@cindex spam filters, SpamAssassin SpamAssassin is one of the more popular spam filtering programs. Get it from your local distribution or from the diff --git a/etc/MH-E-NEWS b/etc/MH-E-NEWS index 7e852afb71..6e1f4db1ed 100644 --- a/etc/MH-E-NEWS +++ b/etc/MH-E-NEWS @@ -13,7 +13,7 @@ Version 8.6 fixes composition errors in nmh 1.6. A components file is now generated that works with nmh 1.5 (partially closes SF #468). - + *** Error if mh-x-face-file is nil Ensure that `mh-x-face-file' is a string before trying to use it @@ -284,7 +284,7 @@ This has been fixed (closes SF #1565460). *** Errors Associated with mh-junk-background -The Spamassassin filter commands were used inconsistently and +The SpamAssassin filter commands were used inconsistently and incorrectly; if `mh-junk-background' were nil, not all of the updating would happen correctly. In the other back-ends such as bogofilter and SpamProbe, a value of t for `mh-junk-background' would cause the @@ -1147,9 +1147,9 @@ The -face suffix has been dropped from all face names. Items in swish indexes that aren't mail messages are now handled more gracefully. -*** Spamassassin Fixes +*** SpamAssassin Fixes -If you use spamassassin, there was an error when you tried to junk +If you use SpamAssassin, there was an error when you tried to junk mail if the option `mh-junk-background' was set. This has been fixed. *** Mairix Support diff --git a/lisp/gnus/ChangeLog.3 b/lisp/gnus/ChangeLog.3 index 5f07d3f0d3..a799f73f58 100644 --- a/lisp/gnus/ChangeLog.3 +++ b/lisp/gnus/ChangeLog.3 @@ -18843,7 +18843,7 @@ * spam.el (spam-spamassassin-score-regexp): New internal variable. (spam-extra-header-to-number, spam-check-spamassassin-headers): - Use it to match format of Spamassassin 3.0 and later. + Use it to match format of SpamAssassin 3.0 and later. Reported by IRIE Tetsuya . (spam-check-bogofilter) (spam-bogofilter-register-with-bogofilter): Fix args of @@ -19031,7 +19031,7 @@ 2006-02-14 Reiner Steib * spam.el (spam-check-spamassassin-headers): Adapt format for - Spamassassin 3.0 or later. Reported by ARISAWA Akihiro + SpamAssassin 3.0 or later. Reported by ARISAWA Akihiro . (spam-list-of-processors): Add spam-use-gmane. diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el index 54c3daa423..25e116cb28 100644 --- a/lisp/mh-e/mh-junk.el +++ b/lisp/mh-e/mh-junk.el @@ -169,7 +169,7 @@ classified as spam (see the option `mh-junk-program')." -;; Spamassassin Interface +;; SpamAssassin Interface (defvar mh-spamassassin-executable (executable-find "spamassassin")) (defvar mh-sa-learn-executable (executable-find "sa-learn")) commit 1d5eeb64da5a8b133c559bb01a9e659255a55af4 Author: Paul Eggert Date: Tue May 30 08:22:27 2017 -0700 Update .gitattributes to match sources better * .gitattributes: Remove nt/nmake.defs. Move dostorture.c, c.C, algrthms.html. Use pattern for todo-mode. Improve patterns for Ada, C, ObjC, shell. Add Pascal. Remove unused pattern *.ruby. Add config.guess and config.sub as shell files. diff --git a/.gitattributes b/.gitattributes index 7e35433dcc..d523e13f3c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,15 +24,12 @@ admin/charsets/mapfiles/PTCP154 whitespace=cr-at-eol leim/MISC-DIC/cangjie-table.b5 whitespace=cr-at-eol leim/MISC-DIC/cangjie-table.cns whitespace=cr-at-eol leim/MISC-DIC/pinyin.map whitespace=cr-at-eol -nt/nmake.defs whitespace=cr-at-eol -test/etags/c-src/dostorture.c whitespace=cr-at-eol -test/etags/cp-src/c.C whitespace=cr-at-eol -test/etags/html-src/algrthms.html whitespace=cr-at-eol +test/manual/etags/c-src/dostorture.c whitespace=cr-at-eol +test/manual/etags/cp-src/c.C whitespace=cr-at-eol +test/manual/etags/html-src/algrthms.html whitespace=cr-at-eol -# The todo-mode file format includes trailing whitespace, so the test -# data files cannot avoid it. -test/lisp/calendar/todo-mode-resources/todo-test-1.toda -whitespace=blank-at-eol -test/lisp/calendar/todo-mode-resources/todo-test-1.todo -whitespace=blank-at-eol +# The todo-mode file format includes trailing whitespace. +*.tod[aorty] -whitespace=blank-at-eol # The upstream maintainer does not want to remove trailing whitespace. doc/misc/texinfo.tex -whitespace=blank-at-eol @@ -52,23 +49,23 @@ doc/misc/texinfo.tex -whitespace=blank-at-eol etc/e/eterm-color binary # Git's builtin diff hunk header styles. -*.ada diff=ada -*.[ch] diff=cpp +*.ad[abs] diff=ada +*.[Cch] diff=cpp *.cc diff=cpp -*.cpp diff=cpp +*.[ch]pp diff=cpp *.hh diff=cpp *.for diff=fortran *.html diff=html *.shtml diff=html *.xml diff=html *.java diff=java -*.m diff=objc +*.[HMm] diff=objc +*.pas diff=pascal *.perl diff=perl *.pl diff=perl *.php diff=php *.py diff=python *.rb diff=ruby -*.ruby diff=ruby *.tex diff=tex # Hooks for non-default diff hunk headers; see autogen.sh. @@ -78,7 +75,7 @@ etc/e/eterm-color binary *.mk diff=make *[Mm]akefile diff=make Makefile.in diff=make -*.sh diff=shell +*[-.]sh diff=shell *.texi diff=texinfo # # Diff hunk header special-case file names. @@ -91,6 +88,8 @@ admin/merge-pkg-config diff=shell admin/quick-install-emacs diff=shell admin/update-copyright diff=shell admin/update_autogen diff=shell +build-aux/config.guess diff=shell +build-aux/config.sub diff=shell build-aux/git-hooks/commit-msg diff=shell build-aux/git-hooks/pre-commit diff=shell build-aux/gitlog-to-emacslog diff=shell commit 75b849294656fd92e77a2a6281ff4dceaaa38475 Author: Noam Postavsky Date: Mon May 29 22:13:53 2017 -0400 Rename '--new-daemon' to 'fg-daemon' and '--old-daemon' to '--bg-daemon' * doc/emacs/cmdargs.texi (Initial Options): * doc/lispref/os.texi (Startup Summary): * etc/NEWS: * etc/emacs.service: * src/emacs.c (main): * src/lisp.h: Rename '--new-daemon' to 'fg-daemon' and '--old-daemon' to '--bg-daemon'. diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index 6f76ef39d9..0b1a400b36 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -336,16 +336,16 @@ setting @code{inhibit-x-resources} to @code{t} (@pxref{Resources}). @opindex -daemon @itemx --daemon[=@var{name}] @opindex --daemon -@itemx --old-daemon[=@var{name}] -@itemx --new-daemon[=@var{name}] +@itemx --bg-daemon[=@var{name}] +@itemx --fg-daemon[=@var{name}] Start Emacs as a daemon---after Emacs starts up, it starts the Emacs server without opening any frames. (Optionally, you can specify an explicit @var{name} for the server.) You can then use the @command{emacsclient} command to connect to Emacs for editing. @xref{Emacs Server}, for information about using Emacs -as a daemon. An ``old-style'' daemon disconnects from the terminal +as a daemon. A ``background'' daemon disconnects from the terminal and runs in the background (@samp{--daemon} is an alias for -@samp{--old-daemon}). +@samp{--bg-daemon}). @item --no-desktop @opindex --no-desktop diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 438f48c347..e6ec60f923 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -337,10 +337,10 @@ Do not display a splash screen. Run without an interactive terminal. @xref{Batch Mode}. @item --daemon -@itemx --old-daemon -@itemx --new-daemon +@itemx --bg-daemon +@itemx --fg-daemon Do not initialize any display; just start a server. -(An ``old-style'' daemon automatically runs in the background.) +(A ``background'' daemon automatically runs in the background.) @item --no-init-file @itemx -q diff --git a/etc/NEWS b/etc/NEWS index 60066b7c9f..14cada4d4f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -78,10 +78,11 @@ affected by this, as SGI stopped supporting IRIX in December 2013. * Startup Changes in Emacs 26.1 -** New option '--new-daemon'. This is the same as '--daemon', except ++++ +** New option '--fg-daemon'. This is the same as '--daemon', except it runs in the foreground and does not fork. This is intended for modern init systems such as systemd, which manage many of the traditional -aspects of daemon behavior themselves. '--old-daemon' is now an alias +aspects of daemon behavior themselves. '--bg-daemon' is now an alias for '--daemon'. +++ diff --git a/etc/emacs.service b/etc/emacs.service index d9f7fc569d..b29177b120 100644 --- a/etc/emacs.service +++ b/etc/emacs.service @@ -8,7 +8,7 @@ Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ [Service] Type=simple -ExecStart=emacs --new-daemon +ExecStart=emacs --fg-daemon ExecStop=emacsclient --eval "(kill-emacs)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure diff --git a/src/emacs.c b/src/emacs.c index 4477f5bc01..6ed16e8037 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -219,8 +219,8 @@ Initialization options:\n\ "\ --batch do not do interactive display; implies -q\n\ --chdir DIR change to directory DIR\n\ ---daemon, --old-daemon[=NAME] start a (named) server in the background\n\ ---new-daemon[=NAME] start a (named) server in the foreground\n\ +--daemon, --bg-daemon[=NAME] start a (named) server in the background\n\ +--fg-daemon[=NAME] start a (named) server in the foreground\n\ --debug-init enable Emacs Lisp debugger for init file\n\ --display, -d DISPLAY use X server DISPLAY\n\ ", @@ -991,15 +991,15 @@ main (int argc, char **argv) int sockfd = -1; - if (argmatch (argv, argc, "-new-daemon", "--new-daemon", 10, NULL, &skip_args) - || argmatch (argv, argc, "-new-daemon", "--new-daemon", 10, &dname_arg, &skip_args)) + if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL, &skip_args) + || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg, &skip_args)) { daemon_type = 1; /* foreground */ } else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args) || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args) - || argmatch (argv, argc, "-old-daemon", "--old-daemon", 10, NULL, &skip_args) - || argmatch (argv, argc, "-old-daemon", "--old-daemon", 10, &dname_arg, &skip_args)) + || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL, &skip_args) + || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, &dname_arg, &skip_args)) { daemon_type = 2; /* background */ } @@ -1114,7 +1114,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem char fdStr[80]; int fdStrlen = snprintf (fdStr, sizeof fdStr, - "--old-daemon=\n%d,%d\n%s", daemon_pipe[0], + "--bg-daemon=\n%d,%d\n%s", daemon_pipe[0], daemon_pipe[1], dname_arg ? dname_arg : ""); if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) @@ -1711,8 +1711,8 @@ static const struct standard_args standard_args[] = { "-batch", "--batch", 100, 0 }, { "-script", "--script", 100, 1 }, { "-daemon", "--daemon", 99, 0 }, - { "-old-daemon", "--old-daemon", 99, 0 }, - { "-new-daemon", "--new-daemon", 99, 0 }, + { "-bg-daemon", "--bg-daemon", 99, 0 }, + { "-fg-daemon", "--fg-daemon", 99, 0 }, { "-help", "--help", 90, 0 }, { "-nl", "--no-loadup", 70, 0 }, { "-nsl", "--no-site-lisp", 65, 0 }, diff --git a/src/lisp.h b/src/lisp.h index 7290386b25..7b8f1e754d 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4167,7 +4167,7 @@ extern bool no_site_lisp; extern bool build_details; #ifndef WINDOWSNT -/* 0 not a daemon, 1 new-style (foreground), 2 old-style (background). */ +/* 0 not a daemon, 1 foreground daemon, 2 background daemon. */ extern int daemon_type; #define IS_DAEMON (daemon_type != 0) #define DAEMON_RUNNING (daemon_type >= 0) commit 941a2e7347e3a0d393e67872e6151be8cc66d9a2 Author: Glenn Morris Date: Mon May 29 17:50:36 2017 -0700 todo-mode: don't assume an ordering of tests * test/lisp/calendar/todo-mode-tests.el (todo-test-todo-quit02) (todo-test-item-highlighting): Avoid prompting for input file. diff --git a/test/lisp/calendar/todo-mode-tests.el b/test/lisp/calendar/todo-mode-tests.el index 70e355ef02..a0d5f01617 100644 --- a/test/lisp/calendar/todo-mode-tests.el +++ b/test/lisp/calendar/todo-mode-tests.el @@ -5,18 +5,20 @@ ;; Author: Stephen Berman ;; Keywords: calendar -;; This program is free software; you can redistribute it and/or modify +;; 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. -;; This program is distributed in the hope that it will be useful, +;; 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 this program. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -93,6 +95,7 @@ current again." If the buffer made current by invoking todo-quit in a todo-mode buffer is buried by quit-window, the todo-mode buffer should not become current." + (todo-test-get-archive 2) (todo-show) (should (todo-test-is-current-buffer todo-test-file-1)) (let ((dir (dired default-directory))) @@ -105,6 +108,7 @@ become current." (ert-deftest todo-test-item-highlighting () ; bug#27133 "Test whether `todo-toggle-item-highlighting' highlights whole item. In particular, all lines of a multiline item should be highlighted." + (todo-test-get-archive 2) (todo-show) (todo-jump-to-category nil "testcat1") ; For test rerun. (todo-toggle-item-highlighting) commit 2a22a65fe1fd7f75480f6dcfe404b5ce43a2b821 Author: Paul Eggert Date: Mon May 29 17:15:11 2017 -0700 Improve .gdbinit Lisp value pretty-printing * src/.gdbinit (to_string): Use an unsigned representation for Lisp values, as requested by Eli Zaretskii (Bug#27098). Also, use "make_number(N)" for Lisp integers. diff --git a/src/.gdbinit b/src/.gdbinit index 80aa95ba40..b5a974bb38 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -1300,18 +1300,52 @@ if hasattr(gdb, 'printing'): def to_string (self): "Yield a string that can be fed back into GDB." + + # This implementation should work regardless of C compiler, and + # it should not attempt to run any code in the inferior. + EMACS_INT_WIDTH = int(gdb.lookup_symbol("EMACS_INT_WIDTH")[0].value()) + USE_LSB_TAG = int(gdb.lookup_symbol("USE_LSB_TAG")[0].value()) + GCTYPEBITS = 3 + VALBITS = EMACS_INT_WIDTH - GCTYPEBITS + Lisp_Int0 = 2 + Lisp_Int1 = 6 if USE_LSB_TAG else 3 + + # Unpack the Lisp value from its containing structure, if necessary. val = self.val basic_type = gdb.types.get_basic_type (val.type) if (basic_type.code == gdb.TYPE_CODE_STRUCT and gdb.types.has_field (basic_type, "i")): val = val["i"] - # Yield "XIL(N)", where N is a C integer. This helps humans - # distinguish Lisp_Object values from ordinary integers even - # when Lisp_Object is an integer. Perhaps some day the - # pretty-printing could be fancier. + + # For nil, yield "XIL(0)", which is easier to read than "XIL(0x0)". if not val: - return "XIL(0)" # Easier to read than "XIL(0x0)". - return "XIL(0x%x)" % int(val) + return "XIL(0)" + + # Extract the integer representation of the value and its Lisp type. + ival = int(val) + itype = ival >> (0 if USE_LSB_TAG else VALBITS) + itype = itype & ((1 << GCTYPEBITS) - 1) + + # For a Lisp integer N, yield "make_number(N)". + if itype == Lisp_Int0 or itype == Lisp_Int1: + if USE_LSB_TAG: + ival = ival >> (GCTYPEBITS - 1) + elif (ival >> VALBITS) & 1: + ival = ival | (-1 << VALBITS) + else: + ival = ival & ((1 << VALBITS) - 1) + return "make_number(%d)" % ival + + # For non-integers other than nil yield "XIL(N)", where N is a C integer. + # This helps humans distinguish Lisp_Object values from ordinary + # integers even when Lisp_Object is an integer. + # Perhaps some day the pretty-printing could be fancier. + # Prefer the unsigned representation to negative values, converting + # by hand as val.cast(gdb.lookup_type("EMACS_UINT") does not work in + # GDB 7.12.1; see . + if ival < 0: + ival = ival + (1 << EMACS_INT_WIDTH) + return "XIL(0x%x)" % ival def build_pretty_printer (): pp = Emacs_Pretty_Printers ("Emacs") @@ -1321,3 +1355,8 @@ if hasattr(gdb, 'printing'): gdb.printing.register_pretty_printer (gdb.current_objfile (), build_pretty_printer (), True) end + +# GDB mishandles indentation with leading tabs when feeding it to Python. +# Local Variables: +# indent-tabs-mode: nil +# End: commit 2349f1df1b11381c421287670ffd0f84725d7818 Author: Dmitry Gutov Date: Tue May 30 02:55:28 2017 +0300 Turn global-eldoc-mode into a globalized minor mode * lisp/emacs-lisp/eldoc.el (global-eldoc-mode): Turn into globalized mode (bug#19853). (turn-on-eldoc-mode): Make it into a wrapper instead of alias. (eldoc-mode): Only show the message when called interactively. diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 6cb8e6ce48..b0f6ea4412 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -187,7 +187,8 @@ expression point is on." (setq eldoc-last-message nil) (cond ((memq eldoc-documentation-function '(nil ignore)) - (message "There is no ElDoc support in this buffer") + (when (called-interactively-p 'any) + (message "There is no ElDoc support in this buffer")) (setq eldoc-mode nil)) (eldoc-mode (when eldoc-print-after-edit @@ -203,29 +204,17 @@ expression point is on." (setq eldoc-timer nil))))) ;;;###autoload -(define-minor-mode global-eldoc-mode - "Toggle Global Eldoc mode on or off. -With a prefix argument ARG, enable Global Eldoc mode if ARG is -positive, and disable it otherwise. If called from Lisp, enable -the mode if ARG is omitted or nil, and toggle it if ARG is ‘toggle’. - -If Global Eldoc mode is on, `eldoc-mode' will be enabled in all -buffers where it's applicable. These are buffers that have modes -that have enabled eldoc support. See `eldoc-documentation-function'." +(define-globalized-minor-mode global-eldoc-mode eldoc-mode turn-on-eldoc-mode :group 'eldoc - :global t :initialize 'custom-initialize-delay - :init-value t - (setq eldoc-last-message nil) - (if global-eldoc-mode - (progn - (add-hook 'post-command-hook #'eldoc-schedule-timer) - (add-hook 'pre-command-hook #'eldoc-pre-command-refresh-echo-area)) - (remove-hook 'post-command-hook #'eldoc-schedule-timer) - (remove-hook 'pre-command-hook #'eldoc-pre-command-refresh-echo-area))) + :init-value t) ;;;###autoload -(define-obsolete-function-alias 'turn-on-eldoc-mode 'eldoc-mode "24.4") +(defun turn-on-eldoc-mode () + "Turn on `eldoc-mode' if the buffer has eldoc support enabled. +See `eldoc-documentation-function' for more detail." + (unless (memq eldoc-documentation-function '(nil ignore)) + (eldoc-mode 1))) (defun eldoc-schedule-timer () commit 4886b2ed52249597d1ea638f20c0ceb689075e72 Author: Dmitry Gutov Date: Tue May 30 00:58:39 2017 +0300 Use regexp matching instead of checking exit status * lisp/progmodes/xref.el (xref-collect-matches): See if the output buffer contents look like Grep output instead of checking exit status (bug#23451). diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index c43f3a4ca8..b8ec50f14a 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -935,11 +935,14 @@ IGNORES is a list of glob patterns." (erase-buffer) (setq status (call-process-shell-command command nil t)) - (when (and (not (zerop status)) - ;; Nonzero status can mean "no matches found". - (/= (point-min) (point-max))) - (user-error "Search failed with status %d: %s" status (buffer-string))) (goto-char (point-min)) + ;; Can't use the exit status: Grep exits with 1 to mean "no + ;; matches found". Find exits with 1 if any of the invocations + ;; exit with non-zero. "No matches" and "Grep program not found" + ;; are all the same to it. + (when (and (/= (point-min) (point-max)) + (not (looking-at grep-re))) + (user-error "Search failed with status %d: %s" status (buffer-string))) (while (re-search-forward grep-re nil t) (push (list (string-to-number (match-string 2)) (match-string 1) commit 299a96c7f6f8dbba210c373130cd9f2d4eec77a5 Author: Stephen Berman Date: Mon May 29 23:49:41 2017 +0200 Add initial tests for todo-mode.el *test/lisp/calendar/todo-mode-tests.el: *test/lisp/calendar/todo-mode-resources/todo-test-1.toda: *test/lisp/calendar/todo-mode-resources/todo-test-1.todo: New files. * .gitattributes: Ignore trailing whitespace in todo-mode test data files, since it is part of the todo-mode file format. diff --git a/.gitattributes b/.gitattributes index 59cc2eded5..7e35433dcc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -29,6 +29,11 @@ test/etags/c-src/dostorture.c whitespace=cr-at-eol test/etags/cp-src/c.C whitespace=cr-at-eol test/etags/html-src/algrthms.html whitespace=cr-at-eol +# The todo-mode file format includes trailing whitespace, so the test +# data files cannot avoid it. +test/lisp/calendar/todo-mode-resources/todo-test-1.toda -whitespace=blank-at-eol +test/lisp/calendar/todo-mode-resources/todo-test-1.todo -whitespace=blank-at-eol + # The upstream maintainer does not want to remove trailing whitespace. doc/misc/texinfo.tex -whitespace=blank-at-eol diff --git a/test/lisp/calendar/todo-mode-resources/todo-test-1.toda b/test/lisp/calendar/todo-mode-resources/todo-test-1.toda new file mode 100644 index 0000000000..8ca4e1908d --- /dev/null +++ b/test/lisp/calendar/todo-mode-resources/todo-test-1.toda @@ -0,0 +1,13 @@ +(("testcat1" . [0 0 1 0]) ("testcat2" . [0 0 1 0]) ("testcat3" . [0 0 1 0])) +--==-- testcat1 + +==--== DONE +[DONE May 26, 2017] [May 26, 2017] testcat1 item1 +--==-- testcat2 + +==--== DONE +[DONE May 28, 2017] [May 28, 2017] testcat2 item1 +--==-- testcat3 + +==--== DONE +[DONE May 28, 2017] [May 28, 2017] testcat3 item1 diff --git a/test/lisp/calendar/todo-mode-resources/todo-test-1.todo b/test/lisp/calendar/todo-mode-resources/todo-test-1.todo new file mode 100644 index 0000000000..8e845df6b6 --- /dev/null +++ b/test/lisp/calendar/todo-mode-resources/todo-test-1.todo @@ -0,0 +1,12 @@ +(("testcat1" . [2 0 0 1]) ("testcat2" . [1 0 0 1])) +--==-- testcat1 +[May 29, 2017] testcat1 item3 + has more than one line + to test item highlighting +[May 26, 2017] testcat1 item2 + +==--== DONE +--==-- testcat2 +[May 28, 2017] testcat2 item2 + +==--== DONE diff --git a/test/lisp/calendar/todo-mode-tests.el b/test/lisp/calendar/todo-mode-tests.el new file mode 100644 index 0000000000..70e355ef02 --- /dev/null +++ b/test/lisp/calendar/todo-mode-tests.el @@ -0,0 +1,124 @@ +;;; todo-mode-tests.el --- tests for todo-mode.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Free Software Foundation, Inc. + +;; Author: Stephen Berman +;; Keywords: calendar + +;; This program 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. + +;; This program 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 this program. If not, see . + +;;; Commentary: + +;; FIXME: +;; In its current form this file changes global variables defined in +;; todo-mode.el, so to avoid problems, these tests should not be run +;; if todo-mode.el is already loaded. + +;;; Code: + +(require 'ert) +(require 'todo-mode) + +(defvar todo-test-data-dir + (file-truename + (expand-file-name "todo-mode-resources/" + (file-name-directory (or load-file-name + buffer-file-name)))) + "Base directory of todo-mode.el test data files.") + +(defvar todo-test-file-1 (expand-file-name "todo-test-1.todo" + todo-test-data-dir) + "Todo mode test file.") + +(defvar todo-test-archive-1 (expand-file-name "todo-test-1.toda" + todo-test-data-dir) + "Todo Archive mode test file.") + +;; (setq todo-directory-orig todo-directory) + +(setq todo-directory todo-test-data-dir) + +(defun todo-test-get-archive (num) + "Make buffer displaying archive category NUM current." + (let ((archive-buf (find-file-noselect todo-test-archive-1))) + (set-buffer archive-buf) + (todo-archive-mode) + (setq todo-category-number num) + (todo-category-select))) + +(defun todo-test-is-current-buffer (filename) + "Return non-nil if FILENAME's buffer is current." + (let ((bufname (buffer-file-name (current-buffer)))) + (and bufname (equal (file-truename bufname) filename)))) + +(ert-deftest todo-test-todo-quit01 () + "Test the behavior of todo-quit with archive and todo files. +Invoking todo-quit in todo-archive-mode should make the +corresponding todo-mode category current, if it exits, otherwise +the current todo-mode category. Quitting todo-mode without an +intermediate buffer switch should not make the archive buffer +current again." + (todo-test-get-archive 2) + (let ((cat-name (todo-current-category))) + (todo-quit) + (should (todo-test-is-current-buffer todo-test-file-1)) + (should (equal (todo-current-category) cat-name)) + (todo-test-get-archive 1) + (setq cat-name (todo-current-category)) + (todo-quit) + (should (todo-test-is-current-buffer todo-test-file-1)) + (should (equal todo-category-number 1)) + (todo-forward-category) ; Category 2 in todo file now current. + (todo-test-get-archive 3) ; No corresponding category in todo file. + (setq cat-name (todo-current-category)) + (todo-quit) + (should (todo-test-is-current-buffer todo-test-file-1)) + (should (equal todo-category-number 2)) + (todo-quit) + (should-not (todo-test-is-current-buffer todo-test-archive-1)))) + +(ert-deftest todo-test-todo-quit02 () ; bug#27121 + "Test the behavior of todo-quit with todo and non-todo buffers. +If the buffer made current by invoking todo-quit in a todo-mode +buffer is buried by quit-window, the todo-mode buffer should not +become current." + (todo-show) + (should (todo-test-is-current-buffer todo-test-file-1)) + (let ((dir (dired default-directory))) + (todo-show) + (todo-quit) + (should (equal (current-buffer) dir)) + (quit-window) + (should-not (todo-test-is-current-buffer todo-test-file-1)))) + +(ert-deftest todo-test-item-highlighting () ; bug#27133 + "Test whether `todo-toggle-item-highlighting' highlights whole item. +In particular, all lines of a multiline item should be highlighted." + (todo-show) + (todo-jump-to-category nil "testcat1") ; For test rerun. + (todo-toggle-item-highlighting) + (let ((end (1- (todo-item-end))) + (beg (todo-item-start))) + (should (eq (get-char-property beg 'face) 'hl-line)) + (should (eq (get-char-property end 'face) 'hl-line)) + (should (> (count-lines beg end) 1)) + (should (eq (next-single-char-property-change beg 'face) (1+ end)))) + (todo-toggle-item-highlighting)) ; Turn off highlighting (for test rerun). + + +;; FIXME: must do this only after running all tests! +;; (setq todo-directory todo-directory-orig) + +(provide 'todo-mode-tests) +;;; todo-mode-tests.el ends here commit ed222c502b1a0043a8bc606482a11516568a54b6 Author: Stephen Berman Date: Mon May 29 20:26:49 2017 +0200 Make `todo-toggle-item-highlighting' work on multiline items (bug#27133) * lisp/calendar/todo-mode.el (todo-hl-line-range): New named function, replacing an anonymous function for the sake of `describe-variable'. (todo-modes-set-2): Use it as buffer-local value of hl-line-range-function and remove boundp test of this variable, so its value is available on invoking `todo-toggle-item-highlighting'. diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index 8155a4241a..7b27e7049d 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el @@ -6583,17 +6583,19 @@ Added to `window-configuration-change-hook' in Todo mode." (visual-line-mode) (setq wrap-prefix (make-string todo-indent-to-here 32)))) +(defun todo-hl-line-range () + "Make `todo-toggle-item-highlighting' highlight entire item." + (save-excursion + (when (todo-item-end) + (cons (todo-item-start) + (todo-item-end))))) + (defun todo-modes-set-2 () "Make some settings that apply to multiple Todo modes." (add-to-invisibility-spec 'todo) (setq buffer-read-only t) (setq-local desktop-save-buffer 'todo-desktop-save-buffer) - (when (boundp 'hl-line-range-function) - (setq-local hl-line-range-function - (lambda() (save-excursion - (when (todo-item-end) - (cons (todo-item-start) - (todo-item-end)))))))) + (setq-local hl-line-range-function 'todo-hl-line-range)) (defun todo-modes-set-3 () "Make some settings that apply to multiple Todo modes." commit c503188f8079ae73d95abd0bce0f53d104b03205 Author: Alan Third Date: Mon May 29 17:01:44 2017 +0100 Fix build error on macOS 10.6 * src/nsfns.m (compute_tip_xy): Cast NSRect to CGRect and NSPoint to CGPoint. diff --git a/src/nsfns.m b/src/nsfns.m index a69e44bb22..7bac2836fe 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2753,7 +2753,7 @@ and GNUstep implementations ("distributor-specific release /* Find the screen that pt is on. */ for (screen in [NSScreen screens]) #ifdef NS_IMPL_COCOA - if (CGRectContainsPoint ([screen frame], pt)) + if (CGRectContainsPoint ((CGRect)[screen frame], (CGPoint)pt)) #else if (pt.x >= screen.frame.origin.x && pt.x < screen.frame.origin.x + screen.frame.size.width commit 443f37163634319a730133efe9e21933c23dc3c6 Author: Noam Postavsky Date: Mon May 22 12:36:20 2017 -0400 ; Fix backslashes in python-tests * test/lisp/progmodes/python-tests.el (python-indent-after-backslash-1) (python-indent-after-backslash-2) (python-indent-after-backslash-3) (python-indent-after-backslash-4) (python-indent-after-backslash-5) (python-nav-beginning-of-statement-1) (python-nav-end-of-statement-1) (python-nav-forward-statement-1) (python-nav-backward-statement-1) (python-nav-backward-statement-2) (python-info-statement-starts-block-p-2) (python-info-statement-ends-block-p-2) (python-info-beginning-of-statement-p-2) (python-info-end-of-statement-p-2) (python-info-beginning-of-block-p-2) (python-info-end-of-block-p-2) (python-info-line-ends-backslash-p-1) (python-info-beginning-of-backslash-1) (python-info-continuation-line-p-1) (python-info-block-continuation-line-p-1) (python-info-assignment-statement-p-1) (python-info-assignment-continuation-line-p-1): Backslashes in literals should be doubled only once to produce one backslash in the buffer. If there backslashes inside a Python string literal in a Lisp literal, that would need to be doubled twice, but there are no such cases. Note that `python-tests-looking-at' takes a plain string, not a regexp. diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index be03535129..f76ecbbd3d 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -654,8 +654,8 @@ async for a in sequencer(): "The most common case." (python-tests-with-temp-buffer " -from foo.bar.baz import something, something_1 \\\\ - something_2 something_3, \\\\ +from foo.bar.baz import something, something_1 \\ + something_2 something_3, \\ something_4, something_5 " (python-tests-look-at "from foo.bar.baz import something, something_1") @@ -675,14 +675,14 @@ from foo.bar.baz import something, something_1 \\\\ "A pretty extreme complicated case." (python-tests-with-temp-buffer " -objects = Thing.objects.all() \\\\ +objects = Thing.objects.all() \\ .filter( type='toy', status='bought' - ) \\\\ + ) \\ .aggregate( Sum('amount') - ) \\\\ + ) \\ .values_list() " (python-tests-look-at "objects = Thing.objects.all()") @@ -698,7 +698,7 @@ objects = Thing.objects.all() \\\\ (python-tests-look-at "status='bought'") (should (eq (car (python-indent-context)) :inside-paren-newline-start)) (should (= (python-indent-calculate-indentation) 27)) - (python-tests-look-at ") \\\\") + (python-tests-look-at ") \\") (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren)) (should (= (python-indent-calculate-indentation) 23)) (python-tests-look-at ".aggregate(") @@ -708,7 +708,7 @@ objects = Thing.objects.all() \\\\ (python-tests-look-at "Sum('amount')") (should (eq (car (python-indent-context)) :inside-paren-newline-start)) (should (= (python-indent-calculate-indentation) 27)) - (python-tests-look-at ") \\\\") + (python-tests-look-at ") \\") (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren)) (should (= (python-indent-calculate-indentation) 23)) (python-tests-look-at ".values_list()") @@ -723,12 +723,12 @@ objects = Thing.objects.all() \\\\ "Backslash continuation from block start." (python-tests-with-temp-buffer " -with open('/path/to/some/file/you/want/to/read') as file_1, \\\\ +with open('/path/to/some/file/you/want/to/read') as file_1, \\ open('/path/to/some/file/being/written', 'w') as file_2: file_2.write(file_1.read()) " (python-tests-look-at - "with open('/path/to/some/file/you/want/to/read') as file_1, \\\\") + "with open('/path/to/some/file/you/want/to/read') as file_1, \\") (should (eq (car (python-indent-context)) :no-indent)) (should (= (python-indent-calculate-indentation) 0)) (python-tests-look-at @@ -744,15 +744,15 @@ with open('/path/to/some/file/you/want/to/read') as file_1, \\\\ "Backslash continuation from assignment." (python-tests-with-temp-buffer " -super_awful_assignment = some_calculation() and \\\\ - another_calculation() and \\\\ +super_awful_assignment = some_calculation() and \\ + another_calculation() and \\ some_final_calculation() " (python-tests-look-at - "super_awful_assignment = some_calculation() and \\\\") + "super_awful_assignment = some_calculation() and \\") (should (eq (car (python-indent-context)) :no-indent)) (should (= (python-indent-calculate-indentation) 0)) - (python-tests-look-at "another_calculation() and \\\\") + (python-tests-look-at "another_calculation() and \\") (should (eq (car (python-indent-context)) :after-backslash-assignment-continuation)) (should (= (python-indent-calculate-indentation) python-indent-offset)) @@ -765,14 +765,14 @@ super_awful_assignment = some_calculation() and \\\\ (python-tests-with-temp-buffer " def delete_all_things(): - Thing \\\\ - .objects.all() \\\\ + Thing \\ + .objects.all() \\ .delete() " - (python-tests-look-at "Thing \\\\") + (python-tests-look-at "Thing \\") (should (eq (car (python-indent-context)) :after-block-start)) (should (= (python-indent-calculate-indentation) 4)) - (python-tests-look-at ".objects.all() \\\\") + (python-tests-look-at ".objects.all() \\") (should (eq (car (python-indent-context)) :after-backslash-first-line)) (should (= (python-indent-calculate-indentation) 8)) (python-tests-look-at ".delete()") @@ -1874,8 +1874,8 @@ class A(object): (ert-deftest python-nav-beginning-of-statement-1 () (python-tests-with-temp-buffer " -v1 = 123 + \ - 456 + \ +v1 = 123 + \\ + 456 + \\ 789 v2 = (value1, value2, @@ -1922,8 +1922,8 @@ string (ert-deftest python-nav-end-of-statement-1 () (python-tests-with-temp-buffer " -v1 = 123 + \ - 456 + \ +v1 = 123 + \\ + 456 + \\ 789 v2 = (value1, value2, @@ -1976,8 +1976,8 @@ string (ert-deftest python-nav-forward-statement-1 () (python-tests-with-temp-buffer " -v1 = 123 + \ - 456 + \ +v1 = 123 + \\ + 456 + \\ 789 v2 = (value1, value2, @@ -2017,8 +2017,8 @@ string (ert-deftest python-nav-backward-statement-1 () (python-tests-with-temp-buffer " -v1 = 123 + \ - 456 + \ +v1 = 123 + \\ + 456 + \\ 789 v2 = (value1, value2, @@ -2059,8 +2059,8 @@ string :expected-result :failed (python-tests-with-temp-buffer " -v1 = 123 + \ - 456 + \ +v1 = 123 + \\ + 456 + \\ 789 v2 = (value1, value2, @@ -3954,8 +3954,8 @@ def long_function_name( (ert-deftest python-info-statement-starts-block-p-2 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError('sorry, you lose') " @@ -3979,8 +3979,8 @@ def long_function_name( (ert-deftest python-info-statement-ends-block-p-2 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4010,8 +4010,8 @@ def long_function_name( (ert-deftest python-info-beginning-of-statement-p-2 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4050,8 +4050,8 @@ def long_function_name( (ert-deftest python-info-end-of-statement-p-2 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4091,8 +4091,8 @@ def long_function_name( (ert-deftest python-info-beginning-of-block-p-2 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4129,8 +4129,8 @@ def long_function_name( (ert-deftest python-info-end-of-block-p-2 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4637,14 +4637,14 @@ elif b: (ert-deftest python-info-line-ends-backslash-p-1 () (python-tests-with-temp-buffer " -objects = Thing.objects.all() \\\\ +objects = Thing.objects.all() \\ .filter( type='toy', status='bought' - ) \\\\ + ) \\ .aggregate( Sum('amount') - ) \\\\ + ) \\ .values_list() " (should (python-info-line-ends-backslash-p 2)) ; .filter(... @@ -4660,14 +4660,14 @@ objects = Thing.objects.all() \\\\ (ert-deftest python-info-beginning-of-backslash-1 () (python-tests-with-temp-buffer " -objects = Thing.objects.all() \\\\ +objects = Thing.objects.all() \\ .filter( type='toy', status='bought' - ) \\\\ + ) \\ .aggregate( Sum('amount') - ) \\\\ + ) \\ .values_list() " (let ((first 2) @@ -4686,8 +4686,8 @@ objects = Thing.objects.all() \\\\ (ert-deftest python-info-continuation-line-p-1 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4714,8 +4714,8 @@ if width == 0 and height == 0 and \\\\ (ert-deftest python-info-block-continuation-line-p-1 () (python-tests-with-temp-buffer " -if width == 0 and height == 0 and \\\\ - color == 'red' and emphasis == 'strong' or \\\\ +if width == 0 and height == 0 and \\ + color == 'red' and emphasis == 'strong' or \\ highlight > 100: raise ValueError( 'sorry, you lose' @@ -4749,8 +4749,8 @@ def foo(a, (ert-deftest python-info-assignment-statement-p-1 () (python-tests-with-temp-buffer " -data = foo(), bar() \\\\ - baz(), 4 \\\\ +data = foo(), bar() \\ + baz(), 4 \\ 5, 6 " (python-tests-look-at "data = foo(), bar()") @@ -4792,8 +4792,8 @@ data '=' 42 (ert-deftest python-info-assignment-continuation-line-p-1 () (python-tests-with-temp-buffer " -data = foo(), bar() \\\\ - baz(), 4 \\\\ +data = foo(), bar() \\ + baz(), 4 \\ 5, 6 " (python-tests-look-at "data = foo(), bar()") commit eafc985f7ea975f86b22d9456a2f91fe5342a9ca Author: Noam Postavsky Date: Mon May 22 12:32:04 2017 -0400 ; Update test for previous change * test/lisp/progmodes/python-tests.el (python-indent-after-backslash-4): Indent after backslash is now python-indent-offset. diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 9aaae396a6..be03535129 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -745,8 +745,8 @@ with open('/path/to/some/file/you/want/to/read') as file_1, \\\\ (python-tests-with-temp-buffer " super_awful_assignment = some_calculation() and \\\\ - another_calculation() and \\\\ - some_final_calculation() + another_calculation() and \\\\ + some_final_calculation() " (python-tests-look-at "super_awful_assignment = some_calculation() and \\\\") @@ -755,10 +755,10 @@ super_awful_assignment = some_calculation() and \\\\ (python-tests-look-at "another_calculation() and \\\\") (should (eq (car (python-indent-context)) :after-backslash-assignment-continuation)) - (should (= (python-indent-calculate-indentation) 25)) + (should (= (python-indent-calculate-indentation) python-indent-offset)) (python-tests-look-at "some_final_calculation()") (should (eq (car (python-indent-context)) :after-backslash)) - (should (= (python-indent-calculate-indentation) 25)))) + (should (= (python-indent-calculate-indentation) python-indent-offset)))) (ert-deftest python-indent-after-backslash-5 () "Dotted continuation bizarre example." commit c9097e9b5f5e427c7d2438db9aad190222882aa1 Author: Jules Tamagnan Date: Thu Oct 27 15:03:31 2016 -0700 Comply with pep 8 style guide for backslash in assignment (Bug#24809) * lisp/progmodes/python.el (python-indent--calculate-indentation): Increase indent by `python-indent-offset' after `:after-backslash-assignment-continuation'. Copyright-paperwork-exempt: yes diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 2697f1a310..4eecfba2e7 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1048,13 +1048,13 @@ possibilities can be narrowed to specific indentation points." (max line-indentation base-indent))) (`(,(or :after-block-start :after-backslash-first-line + :after-backslash-assignment-continuation :inside-paren-newline-start) . ,start) ;; Add one indentation level. (goto-char start) (+ (current-indentation) python-indent-offset)) (`(,(or :inside-paren :after-backslash-block-continuation - :after-backslash-assignment-continuation :after-backslash-dotted-continuation) . ,start) ;; Use the column given by the context. (goto-char start) commit c5cde97ba3a28f3a55a6584c78a7455712a77825 Author: Wilfred Hughes Date: Mon May 29 01:04:41 2017 +0100 Add suggestion to docstring * lisp/subr.el (interactive-p): Mention commandp, as this is often what users are actually looking for. diff --git a/lisp/subr.el b/lisp/subr.el index 8d5d2a779c..0dce02de8b 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4649,7 +4649,10 @@ called from a keyboard macro or in batch mode? To test whether your function was called with `call-interactively', either (i) add an extra optional argument and give it an `interactive' spec that specifies non-nil unconditionally (such as \"p\"); or (ii) -use `called-interactively-p'." +use `called-interactively-p'. + +To test whether a function can be called interactively, use +`commandp'." (declare (obsolete called-interactively-p "23.2")) (called-interactively-p 'interactive)) commit f7c4bad17d83297ee9a1b57552b1944020f23aea Author: Wilfred Hughes Date: Mon May 29 01:00:05 2017 +0100 Ensure button-get works in any buffer * lisp/button.el (button-get): Previously we assumed that button-get was called in the buffer containing the button. In other buffers, button-get always returned nil. Fix this by passing the relevant buffer from the marker. diff --git a/lisp/button.el b/lisp/button.el index b04bc283e4..99c03d9d68 100644 --- a/lisp/button.el +++ b/lisp/button.el @@ -194,6 +194,8 @@ changes to a supertype are not reflected in its subtypes)." ((button--area-button-p button) (get-text-property (cdr button) prop (button--area-button-string button))) + ((markerp button) + (get-text-property button prop (marker-buffer button))) (t ; Must be a text-property button. (get-text-property button prop)))) commit 3bc3dc406343bd7e50acae7c0f9d5f8cc89420cd Author: Dmitry Gutov Date: Mon May 29 02:55:42 2017 +0300 Signal error if find-grep returns a nonzero status * lisp/progmodes/xref.el (xref-collect-matches): Signal error if find-grep returns a nonzero status (bug#23451). Remove the comment: even if some output is present, a non-zero status means something went wrong and it can't be relied upon. diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 9b6a560971..c43f3a4ca8 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -929,14 +929,16 @@ IGNORES is a list of glob patterns." ignores)) (buf (get-buffer-create " *xref-grep*")) (grep-re (caar grep-regexp-alist)) + status hits) (with-current-buffer buf (erase-buffer) - (call-process-shell-command command nil t) - ;; FIXME: What to do when the call fails? - ;; "find: ‘xyzgrep’: No such file or directory\n" - ;; The problem is, find-grep can exit with a nonzero code even - ;; when there are some matches in the output. + (setq status + (call-process-shell-command command nil t)) + (when (and (not (zerop status)) + ;; Nonzero status can mean "no matches found". + (/= (point-min) (point-max))) + (user-error "Search failed with status %d: %s" status (buffer-string))) (goto-char (point-min)) (while (re-search-forward grep-re nil t) (push (list (string-to-number (match-string 2)) commit d76c0078986b72bd83741f16f4db83c1b31de520 Author: Stephen Berman Date: Sun May 28 22:52:05 2017 +0200 Make sure exiting todo-mode buffer buries it (bug#27121) This failed due to commit ea3ae33b from 2013-05-16, which prevented quitting todo-mode buffer after visiting todo-archive buffer from making the archive buffer current again. Avoid this now by simply killing the archive buffer, since there's no need to keep it a live buffer. Consequently, quitting a todo-mode buffer can now use bury-buffer without an argument, which ensures that is will not becomes current on quitting the buffer that replaced it in the window. * lisp/calendar/todo-mode.el (todo-quit): Kill todo-archive-mode buffer instead of burying it. This now allows exiting the todo-mode buffer by bury-buffer without an argument, so do that. diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index 5d4fcf8fcb..8155a4241a 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el @@ -820,14 +820,10 @@ buries it and restores state as needed." (message "There is no todo file for this archive"))) ;; When todo-check-file runs in todo-show, it kills the ;; buffer if the archive file was deleted externally. - (when (buffer-live-p buf) (bury-buffer buf))) + (when (buffer-live-p buf) (kill-buffer buf))) ((eq major-mode 'todo-mode) (todo-save) - ;; If we just quit archive mode, just burying the buffer - ;; in todo-mode would return to archive. - (set-window-buffer (selected-window) - (set-buffer (other-buffer))) - (bury-buffer buf))))) + (bury-buffer))))) ;; ----------------------------------------------------------------------------- ;;; Navigation between and within categories commit e7bb7cc29bc27b368a066c088943c93b1c689b23 Author: Michael Albinus Date: Sun May 28 23:44:10 2017 +0200 Some tweaks, almost all for Tramp adb method * lisp/net/tramp-adb.el (tramp-adb-parse-device-names): Use `make-tramp-file-name'. (tramp-adb-get-device): Use `tramp-file-name-port-or-default'. (tramp-adb-maybe-open-connection): Set "prompt" property. (tramp-adb-wait-for-output): Use it. * lisp/net/tramp-cache.el (tramp-cache-print): Use `elt'. (tramp-dump-connection-properties): Check also that there are properties to be saved. Don't save "started" property of "ftp" method. * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-expand-file-name): Use `make-tramp-file-name'. * lisp/net/tramp.el (tramp-remote-file-name-spec-regexp): Host could be empty. (tramp-file-name-port-or-default): New defun. (tramp-dissect-file-name): Simplify `make-tramp-file-name' call. (tramp-handle-file-name-case-insensitive-p): Use a progress reporter. (tramp-call-process, tramp-call-process-region): Use `make-tramp-file-name'. * test/lisp/net/tramp-tests.el (tramp-test03-file-name-defaults): Revert change from 2017-05-24. (tramp-test05-expand-file-name-relative): Let it also pass for "adb" method. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index e9a3d00134..23aa90186a 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -200,9 +200,9 @@ pass to the OPERATION." ;; That's why we use `start-process'. (let ((p (start-process tramp-adb-program (current-buffer) tramp-adb-program "devices")) - (v (tramp-make-tramp-file-name - tramp-adb-method tramp-current-user nil - tramp-current-host nil nil nil)) + (v (make-tramp-file-name + :method tramp-adb-method :user tramp-current-user + :host tramp-current-host)) result) (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) (process-put p 'adjust-window-size-function 'ignore) @@ -1069,7 +1069,7 @@ E.g. a host name \"192.168.1.1#5555\" returns \"192.168.1.1:5555\" (tramp-flush-connection-property nil) (with-tramp-connection-property (tramp-get-connection-process vec) "device" (let* ((host (tramp-file-name-host vec)) - (port (tramp-file-name-port vec)) + (port (tramp-file-name-port-or-default vec)) (devices (mapcar 'cadr (tramp-adb-parse-device-names nil)))) (replace-regexp-in-string tramp-prefix-port-format ":" @@ -1170,7 +1170,9 @@ FMT and ARGS are passed to `error'." (delete-process proc) (tramp-error proc 'file-error "Process `%s' not available, try again" proc)) (with-current-buffer (process-buffer proc) - (if (tramp-wait-for-regexp proc timeout tramp-adb-prompt) + (if (tramp-wait-for-regexp + proc timeout + (tramp-get-connection-property proc "prompt" tramp-adb-prompt)) (let (buffer-read-only) (goto-char (point-min)) ;; ADB terminal sends "^H" sequences. @@ -1179,20 +1181,25 @@ FMT and ARGS are passed to `error'." (delete-region (point-min) (point))) ;; Delete the prompt. (goto-char (point-min)) - (when (re-search-forward tramp-adb-prompt (point-at-eol) t) + (when (re-search-forward + (tramp-get-connection-property proc "prompt" tramp-adb-prompt) + (point-at-eol) t) (forward-line 1) (delete-region (point-min) (point))) (goto-char (point-max)) - (re-search-backward tramp-adb-prompt nil t) + (re-search-backward + (tramp-get-connection-property proc "prompt" tramp-adb-prompt) nil t) (delete-region (point) (point-max))) (if timeout (tramp-error proc 'file-error "[[Remote adb prompt `%s' not found in %d secs]]" - tramp-adb-prompt timeout) + (tramp-get-connection-property proc "prompt" tramp-adb-prompt) + timeout) (tramp-error proc 'file-error - "[[Remote prompt `%s' not found]]" tramp-adb-prompt))))) + "[[Remote prompt `%s' not found]]" + (tramp-get-connection-property proc "prompt" tramp-adb-prompt)))))) (defun tramp-adb-maybe-open-connection (vec) "Maybe open a connection VEC. @@ -1228,7 +1235,9 @@ connection if a previous connection has died for some reason." (p (let ((default-directory (tramp-compat-temporary-file-directory))) (apply 'start-process (tramp-get-connection-name vec) buf - tramp-adb-program args)))) + tramp-adb-program args))) + (prompt (md5 (concat (prin1-to-string process-environment) + (current-time-string))))) (tramp-message vec 6 "%s" (mapconcat 'identity (process-command p) " ")) ;; Wait for initial prompt. @@ -1239,6 +1248,12 @@ connection if a previous connection has died for some reason." (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) + ;; Change prompt. + (tramp-set-connection-property + p "prompt" (regexp-quote (format "///%s#$" prompt))) + (tramp-adb-send-command + vec (format "PS1=\"///\"\"%s\"\"#$\"" prompt)) + ;; Check whether the properties have been changed. If ;; yes, this is a strong indication that we must expire all ;; connection properties. We start again. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index a863860abf..415cde2fc8 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -326,8 +326,8 @@ used to cache connection properties of the local machine." ;; (substring-no-properties ;; (cl-struct-slot-value 'tramp-file-name slot key)))))) (dotimes (i (length key)) - (when (stringp (aref key i)) - (aset key i (substring-no-properties (aref key i)))))) + (when (stringp (elt key i)) + (setf (elt key i) (substring-no-properties (elt key i)))))) (when (stringp key) (setq key (substring-no-properties key))) (when (stringp value) @@ -373,12 +373,15 @@ used to cache connection properties of the local machine." ;; Remove temporary data. If there is the key "login-as", we ;; don't save either, because all other properties might ;; depend on the login name, and we want to give the - ;; possibility to use another login name later on. + ;; possibility to use another login name later on. Key + ;; "started" exists for the "ftp" method only, which must be + ;; be kept persistent. (maphash (lambda (key value) - (if (and (tramp-file-name-p key) + (if (and (tramp-file-name-p key) value (not (tramp-file-name-localname key)) - (not (gethash "login-as" value))) + (not (gethash "login-as" value)) + (not (gethash "started" value))) (progn (remhash "process-name" value) (remhash "process-buffer" value) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index c016c7e027..d031c73c3f 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -788,7 +788,9 @@ file names." (when (string-match "\\`\\(~\\)\\(/\\|\\'\\)" localname) (save-match-data (tramp-gvfs-maybe-open-connection - (tramp-make-tramp-file-name method user domain host port "/" hop))) + (make-tramp-file-name + :method method :user user :domain domain + :host host :port port :localname "/" :hop hop))) (setq localname (replace-match (tramp-get-connection-property v "default-location" "~") diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index e75305b637..05d197fce0 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -857,8 +857,9 @@ Derived from `tramp-postfix-host-format'." "\\(" (tramp-method-regexp) "\\)" (tramp-postfix-method-regexp) "\\(?:" "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp "\\)?" "\\(" "\\(?:" tramp-host-regexp "\\|" - (tramp-prefix-ipv6-regexp) "\\(?:" tramp-ipv6-regexp "\\)?" - (tramp-postfix-ipv6-regexp) "\\)" + (tramp-prefix-ipv6-regexp) + "\\(?:" tramp-ipv6-regexp "\\)?" + (tramp-postfix-ipv6-regexp) "\\)?" "\\(?:" tramp-prefix-port-regexp tramp-port-regexp "\\)?" "\\)?")) (defun tramp-file-name-structure () @@ -1135,7 +1136,7 @@ calling HANDLER.") ;; data structure. ;; The basic structure for remote file names. We use a list :type, -;; otherwise the persistent data are not read in tramp-cache.el. +;; in order to be compatible with Emacs 24 and 25. (cl-defstruct (tramp-file-name (:type list) :named) method user domain host port localname hop) @@ -1155,6 +1156,12 @@ calling HANDLER.") tramp-prefix-port-format) (tramp-file-name-port vec)))) +(defun tramp-file-name-port-or-default (vec) + "Return port component of VEC. +If nil, return `tramp-default-port'." + (or (tramp-file-name-port vec) + (tramp-get-method-parameter vec 'tramp-default-port))) + (defun tramp-file-name-equal-p (vec1 vec2) "Check, whether VEC1 and VEC2 denote the same `tramp-file-name'." (and (tramp-file-name-p vec1) (tramp-file-name-p vec2) @@ -1294,16 +1301,9 @@ values." user (tramp-find-user method user host) host (tramp-find-host method user host))) - (apply - 'make-tramp-file-name - (append - (unless (zerop (length method)) `(:method ,method)) - (unless (zerop (length user)) `(:user ,user)) - (unless (zerop (length domain)) `(:domain ,domain)) - (unless (zerop (length host)) `(:host ,host)) - (unless (zerop (length port)) `(:port ,port)) - `(:localname ,(or localname "")) - (unless (zerop (length hop)) `(:hop ,hop)))))))) + (make-tramp-file-name + :method method :user user :domain domain :host host :port port + :localname (or localname "") :hop hop))))) (defun tramp-buffer-name (vec) "A name for the connection buffer VEC." @@ -2878,38 +2878,42 @@ User is always nil." ;; There isn't. So we must check, in case there's a connection already. (and (tramp-connectable-p filename) (with-tramp-connection-property v "case-insensitive" - ;; The idea is to compare a file with lower case letters - ;; with the same file with upper case letters. - (let ((candidate - (tramp-compat-file-name-unquote - (directory-file-name filename))) - tmpfile) - ;; Check, whether we find an existing file with lower case - ;; letters. This avoids us to create a temporary file. - (while (and (string-match - "[a-z]" (file-remote-p candidate 'localname)) - (not (file-exists-p candidate))) - (setq candidate - (directory-file-name (file-name-directory candidate)))) - ;; Nothing found, so we must use a temporary file for - ;; comparison. `make-nearby-temp-file' is added to - ;; Emacs 26+ like `file-name-case-insensitive-p', so - ;; there is no compatibility problem calling it. - (unless - (string-match "[a-z]" (file-remote-p candidate 'localname)) - (setq tmpfile - (let ((default-directory (file-name-directory filename))) - (tramp-compat-funcall 'make-nearby-temp-file "tramp.")) - candidate tmpfile)) - ;; Check for the existence of the same file with upper - ;; case letters. - (unwind-protect - (file-exists-p - (concat - (file-remote-p candidate) - (upcase (file-remote-p candidate 'localname)))) - ;; Cleanup. - (when tmpfile (delete-file tmpfile))))))))) + (with-tramp-progress-reporter v 5 "Checking case-insensitive" + ;; The idea is to compare a file with lower case letters + ;; with the same file with upper case letters. + (let ((candidate + (tramp-compat-file-name-unquote + (directory-file-name filename))) + tmpfile) + ;; Check, whether we find an existing file with lower + ;; case letters. This avoids us to create a temporary + ;; file. + (while (and (string-match + "[a-z]" (file-remote-p candidate 'localname)) + (not (file-exists-p candidate))) + (setq candidate + (directory-file-name (file-name-directory candidate)))) + ;; Nothing found, so we must use a temporary file for + ;; comparison. `make-nearby-temp-file' is added to + ;; Emacs 26+ like `file-name-case-insensitive-p', so + ;; there is no compatibility problem calling it. + (unless + (string-match "[a-z]" (file-remote-p candidate 'localname)) + (setq tmpfile + (let ((default-directory + (file-name-directory filename))) + (tramp-compat-funcall + 'make-nearby-temp-file "tramp.")) + candidate tmpfile)) + ;; Check for the existence of the same file with upper + ;; case letters. + (unwind-protect + (file-exists-p + (concat + (file-remote-p candidate) + (upcase (file-remote-p candidate 'localname)))) + ;; Cleanup. + (when tmpfile (delete-file tmpfile)))))))))) (defun tramp-handle-file-name-completion (filename directory &optional predicate) @@ -4131,9 +4135,10 @@ PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." (let ((default-directory (tramp-compat-temporary-file-directory)) (v (or vec - (tramp-make-tramp-file-name - tramp-current-method tramp-current-user tramp-current-domain - tramp-current-host tramp-current-port nil nil))) + (make-tramp-file-name + :method tramp-current-method :user tramp-current-user + :domain tramp-current-domain :host tramp-current-host + :port tramp-current-port))) (destination (if (eq destination t) (current-buffer) destination)) output error result) (tramp-message @@ -4167,9 +4172,10 @@ PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." (let ((default-directory (tramp-compat-temporary-file-directory)) (v (or vec - (tramp-make-tramp-file-name - tramp-current-method tramp-current-user tramp-current-domain - tramp-current-host tramp-current-port nil nil))) + (make-tramp-file-name + :method tramp-current-method :user tramp-current-user + :domain tramp-current-domain :host tramp-current-host + :port tramp-current-port))) (buffer (if (eq buffer t) (current-buffer) buffer)) result) (tramp-message diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 7a12aae1bf..8c97fafa3e 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -1510,7 +1510,7 @@ handled properly. BODY shall not contain a timeout." (ert-deftest tramp-test03-file-name-defaults () "Check default values for some methods." ;; Default values in tramp-adb.el. - (should (string-equal (file-remote-p "/adb::" 'host) nil)) + (should (string-equal (file-remote-p "/adb::" 'host) "")) ;; Default values in tramp-ftp.el. (should (string-equal (file-remote-p "/-:ftp.host:" 'method) "ftp")) (dolist (u '("ftp" "anonymous")) @@ -1626,7 +1626,7 @@ handled properly. BODY shall not contain a timeout." :expected-result :failed (skip-unless (tramp--test-enabled)) ;; File names with a share behave differently. - (when (tramp--test-afp-or-smb-p) + (when (or (tramp--test-adb-p) (tramp--test-afp-or-smb-p)) (setf (ert-test-expected-result-type (ert-get-test 'tramp-test05-expand-file-name-relative)) :passed)) commit 288b3ca2e519903653b9bc88d281ecd9f6b162a4 Author: Jürgen Hötzel Date: Sun May 28 13:06:53 2017 +0200 Fix Tramp for Android 7 * tramp-adb.el (tramp-adb-ls-toolbox-regexp): Username part of prompt is empty on Android 7. (tramp-adb-ls-toolbox-regexp): Ignore addition links column on Android 7. (tramp-adb-get-ls-command): Dont use --color=none when using toybox (Android 7). It's not possible to disable coloring explicitly for toybox ls. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index a6c2c14212..e9a3d00134 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -58,7 +58,7 @@ It is used for TCP/IP devices." ;;;###tramp-autoload (defcustom tramp-adb-prompt - "^\\(?:[[:digit:]]*|?\\)?\\(?:[[:alnum:]\e;[]*@[[:alnum:]]*[^#\\$]*\\)?[#\\$][[:space:]]" + "^\\(?:[[:digit:]]*|?\\)?\\(?:[[:alnum:]\e;[]*@?[[:alnum:]]*[^#\\$]*\\)?[#\\$][[:space:]]" "Regexp used as prompt in almquist shell." :type 'string :version "24.4" @@ -72,6 +72,7 @@ It is used for TCP/IP devices." (defconst tramp-adb-ls-toolbox-regexp (concat "^[[:space:]]*\\([-[:alpha:]]+\\)" ; \1 permissions + "\\(?:[[:space:]][[:digit:]]+\\)?" ; links (Android 7/ToolBox) "[[:space:]]*\\([^[:space:]]+\\)" ; \2 username "[[:space:]]+\\([^[:space:]]+\\)" ; \3 group "[[:space:]]+\\([[:digit:]]+\\)" ; \4 size @@ -441,12 +442,15 @@ pass to the OPERATION." "Determine `ls' command at its arguments." (with-tramp-connection-property vec "ls" (tramp-message vec 5 "Finding a suitable `ls' command") - (if (tramp-adb-send-command-and-check vec "ls --color=never -al /dev/null") - ;; On CyanogenMod based system BusyBox is used and "ls" output - ;; coloring is enabled by default. So we try to disable it - ;; when possible. - "ls --color=never" - "ls"))) + (cond + ;; Can't disable coloring explicitly for toybox ls command + ((tramp-adb-send-command-and-check vec "toybox") "ls") + ;; On CyanogenMod based system BusyBox is used and "ls" output + ;; coloring is enabled by default. So we try to disable it + ;; when possible. + ((tramp-adb-send-command-and-check vec "ls --color=never -al /dev/null") + "ls --color=never") + (t "ls")))) (defun tramp-adb--gnu-switches-to-ash (switches) "Almquist shell can't handle multiple arguments. commit 527a7cc9425370f7217a4d2b6914b96dff6f5ec1 Author: Svante Carl v. Erichsen Date: Sun Oct 6 20:33:24 2013 +0200 Fix cl-indent for `loop' with :keywords (Bug#15543) * lisp/emacs-lisp/cl-indent.el (lisp-extended-loop-p): Allow for ":keywords". Copyright-paperwork-exempt: yes diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el index 9941d17359..df0e0a8858 100644 --- a/lisp/emacs-lisp/cl-indent.el +++ b/lisp/emacs-lisp/cl-indent.el @@ -166,7 +166,7 @@ is set to `defun'.") (forward-char 1) (forward-sexp 2) (backward-sexp 1) - (looking-at "\\sw")) + (looking-at "\\(:\\|\\sw\\)")) (error t))) (defun lisp-indent-find-method (symbol &optional no-compat) commit d387305062d9dab78b9c3cdc96090496eaf5a1c3 Author: Paul Eggert Date: Sat May 27 10:54:25 2017 -0700 Depromiscuify inotify with IN_MASK_ADD Use IN_MASK_ADD instead of using a no-longer-promiscuous-enough mask. This simplifies the code and restores the ability to use IN_ACCESS, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, and IN_OPEN in some cases (Bug#26973). * src/inotify.c (INOTIFY_DEFAULT_MASK): Remove. (Finotify_add_watch): Use IN_MASK_ADD instead. diff --git a/src/inotify.c b/src/inotify.c index b3e0728690..3d5d3d2621 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -42,21 +42,6 @@ along with GNU Emacs. If not, see . */ # define IN_ONLYDIR 0 #endif -/* Events that inotify-add-watch waits for. This list has all the - events that any watcher could include, because we want to support - multiple watches on the same file even though inotify uses the same - descriptor for all watches to that file. This list omits - IN_ACCESS, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, and IN_OPEN because - they would prevent other processes from reading; see Bug#26973. - - FIXME: Explain why it is OK to omit these four bits here even - though a inotify-add-watch call might specify them. */ - -#define INOTIFY_DEFAULT_MASK \ - (IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF \ - | IN_IGNORED | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM \ - | IN_MOVED_TO | IN_EXCL_UNLINK) - /* File handle for inotify. */ static int inotifyfd = -1; @@ -436,8 +421,7 @@ IN_ONESHOT */) Lisp_Object encoded_file_name; int wd = -1; uint32_t imask = aspect_to_inotifymask (aspect); - uint32_t mask = (INOTIFY_DEFAULT_MASK - | (imask & (IN_DONT_FOLLOW | IN_ONLYDIR))); + uint32_t mask = imask | IN_MASK_ADD | IN_EXCL_UNLINK; CHECK_STRING (filename); commit ad656a726fc2683b0ca5683fcaaf6852f2c876b2 Author: Paul Eggert Date: Sat May 27 10:54:25 2017 -0700 Restore inotify onlydir support There was no need to remove it in the 2017-03-26 inotify change, as it is like IN_DONT_FOLLOW and does not affect other watchers for the same file. * src/inotify.c (symbol_to_inotifymask, Finotify_add_watch) (syms_of_inotify): Bring back onlydir. diff --git a/src/inotify.c b/src/inotify.c index bcf30ad2b3..b3e0728690 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -72,10 +72,6 @@ static int inotifyfd = -1; IN_EXCL_UNLINK IN_MASK_ADD IN_ONESHOT - IN_ONLYDIR - - FIXME: Explain why IN_ONLYDIR is in the list, as it seems to be - in the same category as IN_DONT_FOLLOW which is allowed. Each element of this list is of the form (DESCRIPTOR . WATCHES) where no two DESCRIPTOR values are the same. DESCRIPTOR represents @@ -162,6 +158,8 @@ symbol_to_inotifymask (Lisp_Object symb) else if (EQ (symb, Qdont_follow)) return IN_DONT_FOLLOW; + else if (EQ (symb, Qonlydir)) + return IN_ONLYDIR; else if (EQ (symb, Qt) || EQ (symb, Qall_events)) return IN_ALL_EVENTS; @@ -397,9 +395,11 @@ all-events or t move close -The following symbols can also be added to a list of aspects: +ASPECT can also contain the following symbols, which control whether +the watch descriptor will be created: dont-follow +onlydir Watching a directory is not recursive. CALLBACK is passed a single argument EVENT which contains an event structure of the format @@ -430,15 +430,14 @@ shared across different callers. IN_EXCL_UNLINK IN_MASK_ADD -IN_ONESHOT -IN_ONLYDIR */) +IN_ONESHOT */) (Lisp_Object filename, Lisp_Object aspect, Lisp_Object callback) { Lisp_Object encoded_file_name; int wd = -1; uint32_t imask = aspect_to_inotifymask (aspect); uint32_t mask = (INOTIFY_DEFAULT_MASK - | (imask & IN_DONT_FOLLOW)); + | (imask & (IN_DONT_FOLLOW | IN_ONLYDIR))); CHECK_STRING (filename); @@ -548,6 +547,7 @@ syms_of_inotify (void) DEFSYM (Qclose, "close"); /* IN_CLOSE */ DEFSYM (Qdont_follow, "dont-follow"); /* IN_DONT_FOLLOW */ + DEFSYM (Qonlydir, "onlydir"); /* IN_ONLYDIR */ DEFSYM (Qignored, "ignored"); /* IN_IGNORED */ DEFSYM (Qisdir, "isdir"); /* IN_ISDIR */ commit 8f59ff2461b54e29c9389cee5851f348b867a281 Author: Paul Eggert Date: Sat May 27 10:54:25 2017 -0700 Simplify computation of inotify mask * src/inotify.c (add_watch): Accept uint32_t imask instead of Lisp_Object aspect. Caller changed. (Finotify_add_watch): Use aspect_to_inotifymask earlier, to simplify the code. diff --git a/src/inotify.c b/src/inotify.c index 1165293d24..bcf30ad2b3 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -215,16 +215,15 @@ inotifyevent_to_event (Lisp_Object watch, struct inotify_event const *ev) } /* Add a new watch to watch-descriptor WD watching FILENAME and using - CALLBACK. Returns a cons (DESCRIPTOR . ID) uniquely identifying the - new watch. */ + IMASK and CALLBACK. Return a cons (DESCRIPTOR . ID) uniquely + identifying the new watch. */ static Lisp_Object add_watch (int wd, Lisp_Object filename, - Lisp_Object aspect, Lisp_Object callback) + uint32_t imask, Lisp_Object callback) { Lisp_Object descriptor = INTEGER_TO_CONS (wd); Lisp_Object tail = assoc_no_quit (descriptor, watch_list); Lisp_Object watch, watch_id; - uint32_t imask = aspect_to_inotifymask (aspect); Lisp_Object mask = INTEGER_TO_CONS (imask); EMACS_INT id = 0; @@ -436,12 +435,10 @@ IN_ONLYDIR */) (Lisp_Object filename, Lisp_Object aspect, Lisp_Object callback) { Lisp_Object encoded_file_name; - bool dont_follow = (CONSP (aspect) - ? ! NILP (Fmemq (Qdont_follow, aspect)) - : EQ (Qdont_follow, aspect)); int wd = -1; + uint32_t imask = aspect_to_inotifymask (aspect); uint32_t mask = (INOTIFY_DEFAULT_MASK - | (dont_follow ? IN_DONT_FOLLOW : 0)); + | (imask & IN_DONT_FOLLOW)); CHECK_STRING (filename); @@ -459,7 +456,7 @@ IN_ONLYDIR */) if (wd < 0) report_file_notify_error ("Could not add watch for file", filename); - return add_watch (wd, filename, aspect, callback); + return add_watch (wd, filename, imask, callback); } static bool commit ebe0bdae9ded4eab974faefb54a6ba5260523489 Author: Philipp Stephani Date: Sat May 27 14:39:01 2017 +0200 Don't attempt to recover from undefined behavior in some cases These functions can only be run in batch mode and exit Emacs on return, so nothing can be recovered. Disable unsafe recover mechanisms so that we get real failures and good stack traces on fatal signals. * lisp/emacs-lisp/bytecomp.el (batch-byte-compile) (batch-byte-recompile-directory): * lisp/emacs-lisp/ert.el (ert-run-tests-batch-and-exit) (ert-summarize-tests-batch-and-exit): Don't attempt to recover from undefined behavior. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 6c12e5d8e2..12a7d4afc2 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -4960,6 +4960,10 @@ already up-to-date." (defvar command-line-args-left) ;Avoid 'free variable' warning (if (not noninteractive) (error "`batch-byte-compile' is to be used only with -batch")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (let ((error nil)) (while command-line-args-left (if (file-directory-p (expand-file-name (car command-line-args-left))) @@ -5052,6 +5056,10 @@ and corresponding effects." (defvar command-line-args-left) ;Avoid 'free variable' warning (if (not noninteractive) (error "batch-byte-recompile-directory is to be used only with -batch")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (or command-line-args-left (setq command-line-args-left '("."))) (while command-line-args-left diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 280b76acfe..2c49a634e3 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -1458,6 +1458,12 @@ The exit status will be 0 if all test results were as expected, 1 on unexpected results, or 2 if the tool detected an error outside of the tests (e.g. invalid SELECTOR or bug in the code that runs the tests)." + (or noninteractive + (user-error "This function is only for use in batch mode")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (unwind-protect (let ((stats (ert-run-tests-batch selector))) (kill-emacs (if (zerop (ert-stats-completed-unexpected stats)) 0 1))) @@ -1475,6 +1481,10 @@ The logfiles should have the `ert-run-tests-batch' format. When finished, this exits Emacs, with status as per `ert-run-tests-batch-and-exit'." (or noninteractive (user-error "This function is only for use in batch mode")) + ;; Better crash loudly than attempting to recover from undefined + ;; behavior. + (setq attempt-stack-overflow-recovery nil + attempt-orderly-shutdown-on-fatal-signal nil) (let ((nlogs (length command-line-args-left)) (ntests 0) (nrun 0) (nexpected 0) (nunexpected 0) (nskipped 0) nnotrun logfile notests badtests unexpected skipped) commit a3a3ea0762d0e5d3b2cb8259a515a468736050d1 Author: Philipp Stephani Date: Sat May 27 15:26:49 2017 +0200 Avoid another compiler warning on macOS When configured with --without-ns, HAVE_NS is not defined on macOS, thus 'memory-limit' calls the deprecated sbrk(2) function. Avoid that by using the pre-defined __APPLE__ preprocessor macro. * src/alloc.c (Fmemory_limit): Never use sbrk(2) on macOS. diff --git a/src/alloc.c b/src/alloc.c index b473ebd7de..a1a85946ce 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -7160,7 +7160,7 @@ We divide the value by 1024 to make sure it fits in a Lisp integer. */) { Lisp_Object end; -#if defined HAVE_NS || !HAVE_SBRK +#if defined HAVE_NS || defined __APPLE__ || !HAVE_SBRK /* Avoid warning. sbrk has no relation to memory allocated anyway. */ XSETINT (end, 0); #else commit b0177da7fe51b267de6ffa84a38bd0ec3f6c0fa9 Author: Luke Yen-Xun Lee Date: Sat May 27 16:25:02 2017 +0300 Fix ruler-mode text-scaling issues * lisp/ruler-mode.el (ruler-mode-text-scaled-width): New function for computing scaled text width. (ruler-mode-text-scaled-window-hscroll) (ruler-mode-text-scaled-window-width): Compute text scaled `window-width' value. (ruler-mode-mouse-grab-any-column, ruler-mode-mouse-add-tab-stop) (ruler-mode-ruler): Change `window-hscroll' into `ruler-mode-text-scaled-window-hscroll', and change `window-width' into `ruler-mode-text-scaled-window-width'. diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el index 4f09a1887f..7b0588dfea 100644 --- a/lisp/ruler-mode.el +++ b/lisp/ruler-mode.el @@ -360,6 +360,20 @@ START-EVENT is the mouse click event." That is `fill-column', `comment-column', `goal-column', or nil when nothing is dragged.") +(defun ruler-mode-text-scaled-width (width) + "Compute scaled text width according to current font scaling. +Convert a width of char units into a text-scaled char width units, +Ex. `window-hscroll'." + (/ (* width (frame-char-width)) (default-font-width))) + +(defun ruler-mode-text-scaled-window-hscroll () + "Text scaled `window-hscroll'." + (ruler-mode-text-scaled-width (window-hscroll))) + +(defun ruler-mode-text-scaled-window-width () + "Text scaled `window-width'." + (ruler-mode-text-scaled-width (window-width))) + (defun ruler-mode-mouse-grab-any-column (start-event) "Drag a column symbol on the ruler. Start dragging on mouse down event START-EVENT, and update the column @@ -372,9 +386,9 @@ dragging. See also the variable `ruler-mode-dragged-symbol'." (save-selected-window (select-window (posn-window start)) (setq col (ruler-mode-window-col (car (posn-col-row start))) - newc (+ col (window-hscroll))) + newc (+ col (ruler-mode-text-scaled-window-hscroll))) (and - (>= col 0) (< col (window-width)) + (>= col 0) (< col (ruler-mode-text-scaled-window-width)) (cond ;; Handle the fill column. @@ -457,8 +471,8 @@ Called on each mouse motion event START-EVENT." (save-selected-window (select-window (posn-window start)) (setq col (ruler-mode-window-col (car (posn-col-row end))) - newc (+ col (window-hscroll))) - (when (and (>= col 0) (< col (window-width))) + newc (+ col (ruler-mode-text-scaled-window-hscroll))) + (when (and (>= col 0) (< col (ruler-mode-text-scaled-window-width))) (set ruler-mode-dragged-symbol newc))))) (defun ruler-mode-mouse-add-tab-stop (start-event) @@ -473,8 +487,8 @@ START-EVENT is the mouse click event." (save-selected-window (select-window (posn-window start)) (setq col (ruler-mode-window-col (car (posn-col-row start))) - ts (+ col (window-hscroll))) - (and (>= col 0) (< col (window-width)) + ts (+ col (ruler-mode-text-scaled-window-hscroll))) + (and (>= col 0) (< col (ruler-mode-text-scaled-window-width)) (not (member ts tab-stop-list)) (progn (message "Tab stop set to %d" ts) @@ -494,8 +508,8 @@ START-EVENT is the mouse click event." (save-selected-window (select-window (posn-window start)) (setq col (ruler-mode-window-col (car (posn-col-row start))) - ts (+ col (window-hscroll))) - (and (>= col 0) (< col (window-width)) + ts (+ col (ruler-mode-text-scaled-window-hscroll))) + (and (>= col 0) (< col (ruler-mode-text-scaled-window-width)) (member ts tab-stop-list) (progn (message "Tab stop at %d deleted" ts) @@ -648,11 +662,11 @@ Optional argument PROPS specifies other text properties to apply." (defun ruler-mode-ruler () "Compute and return a header line ruler." - (let* ((w (window-width)) + (let* ((w (ruler-mode-text-scaled-window-width)) (m (window-margins)) (f (window-fringes)) (i 0) - (j (window-hscroll)) + (j (ruler-mode-text-scaled-window-hscroll)) ;; Setup the scrollbar, fringes, and margins areas. (lf (ruler-mode-space 'left-fringe commit 704fea97e495b43e4bbd03f28d0ccc66b45e80a8 Author: Martin Rudalics Date: Sat May 27 15:14:52 2017 +0200 Minor doc and doc-string fixes (Bug#27091) * src/window.c (Fset_window_scroll_bars): Fix doc-string. * doc/lispref/display.texi (Fringe Size/Pos, Scroll Bars) (Display Margins): Mention that `set-window-buffer' may override settings made by `set-window-fringes', `set-window-scroll-bars' and `set-window-margins'. * doc/lispref/windows.texi (Buffers and Windows): Fix doc of `set-window-buffer'. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 51e31aa273..aa75dcf5a0 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -3798,6 +3798,10 @@ fringe, and likewise @var{right} for the right fringe. A value of @code{nil} for either one stands for the default width. If @var{outside-margins} is non-@code{nil}, that specifies that fringes should appear outside of the display margins. + +The values specified here may be later overridden by invoking +@code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window} +with its @var{keep-margins} argument @code{nil} or omitted. @end defun @defun window-fringes &optional window @@ -4200,7 +4204,8 @@ using the following function: @defun set-window-scroll-bars window &optional width vertical-type height horizontal-type This function sets the width and/or height and the types of scroll bars -for window @var{window}. +for window @var{window}. If @var{window} is @code{nil}, the selected +window is used. @var{width} specifies the width of the vertical scroll bar in pixels (@code{nil} means use the width specified for the frame). @@ -4215,7 +4220,9 @@ vertical scroll bar. The possible values are @code{bottom}, @code{t}, which means to use the frame's default, and @code{nil} for no horizontal scroll bar. -If @var{window} is @code{nil}, the selected window is used. +The values specified here may be later overridden by invoking +@code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window} +with its @var{keep-margins} argument @code{nil} or omitted. @end defun The following four functions take as argument a live window which @@ -4759,6 +4766,10 @@ Thus, you can make changes take effect by calling This function specifies the margin widths for window @var{window}, in character cell units. The argument @var{left} controls the left margin, and @var{right} controls the right margin (default @code{0}). + +The values specified here may be later overridden by invoking +@code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window} +with its @var{keep-margins} argument @code{nil} or omitted. @end defun @defun window-margins &optional window diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index b015233753..3a9257e05a 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -2049,8 +2049,8 @@ signals an error. @xref{Dedicated Windows}. By default, this function resets @var{window}'s position, display margins, fringe widths, and scroll bar settings, based on the local variables in the specified buffer. However, if the optional argument -@var{keep-margins} is non-@code{nil}, it leaves the display margins -and fringe widths unchanged. +@var{keep-margins} is non-@code{nil}, it leaves @var{window}'s display +margins, fringes and scroll bar settings alone. When writing an application, you should normally use the higher-level functions described in @ref{Switching Buffers}, instead of calling diff --git a/src/window.c b/src/window.c index fc9f40222b..bf89f0e488 100644 --- a/src/window.c +++ b/src/window.c @@ -3342,7 +3342,7 @@ run_window_size_change_functions (Lisp_Object frame) /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed to run hooks. See make_frame for a case where it's not allowed. KEEP_MARGINS_P means that the current margins, fringes, and - scroll-bar settings of the window are not reset from the buffer's + scroll bar settings of the window are not reset from the buffer's local settings. */ void @@ -7045,16 +7045,18 @@ DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, WINDOW must be a live window and defaults to the selected one. Second parameter WIDTH specifies the pixel width for the vertical scroll -bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame. +bar. If WIDTH is nil, use the scroll bar width of WINDOW's frame. Third parameter VERTICAL-TYPE specifies the type of the vertical scroll -bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the -frame's scroll-bar type. +bar: left, right, nil or t where nil means to not display a vertical +scroll bar on WINDOW and t means to use WINDOW frame's vertical scroll +bar type. Fourth parameter HEIGHT specifies the pixel height for the horizontal -scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's +scroll bar. If HEIGHT is nil, use the scroll bar height of WINDOW's frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the -horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this -means to use the frame's horizontal scroll-bar type. +horizontal scroll bar: bottom, nil, or t where nil means to not display +a horizontal scroll bar on WINDOW and t means to use WINDOW frame's +horizontal scroll bar type. Return t if scroll bars were actually changed and nil otherwise. */) (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, commit 3fc36f427a6dfe5366fd1391fee1d037a1bd6cd7 Author: Eli Zaretskii Date: Sat May 27 15:57:38 2017 +0300 Avoid args-out-of-range errors on fringe clicks after "C-h k" * src/keyboard.c (echo_truncate): Don't call Ftruncate if the echo message is already shorter than NCHARS. (Bug#27040) diff --git a/src/keyboard.c b/src/keyboard.c index c9fa2a9f5e..55486c6d9a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -634,7 +634,8 @@ echo_length (void) static void echo_truncate (ptrdiff_t nchars) { - if (STRINGP (KVAR (current_kboard, echo_string))) + Lisp_Object es = KVAR (current_kboard, echo_string); + if (STRINGP (es) && SCHARS (es) > nchars) kset_echo_string (current_kboard, Fsubstring (KVAR (current_kboard, echo_string), make_number (0), make_number (nchars))); commit 4b17214aab5d108a2b9b060e49ef6a27d43d35b4 Author: Eli Zaretskii Date: Sat May 27 15:15:18 2017 +0300 Fix GUD "Stop" display when running pdb * lisp/progmodes/gud.el (gud-menu-map): Don't call gdb-show-stop-p when GUD mode is 'pdb'. (Bug#27024) diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index 8cb912706f..e9ca7eade3 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -157,7 +157,8 @@ Used to gray out relevant toolbar icons.") (gdb-show-run-p))) ([stop] menu-item "Stop" gud-stop-subjob :visible (or (not (memq gud-minor-mode '(gdbmi pdb))) - (gdb-show-stop-p))) + (and (eq gud-minor-mode 'gdbmi) + (gdb-show-stop-p)))) ([until] menu-item "Continue to selection" gud-until :enable (not gud-running) :visible (and (memq gud-minor-mode '(gdbmi gdb perldb)) commit c0f2c298772fbb1dcaa1da3e9c2760e09147e115 Author: Tak Kunihiro Date: Sat May 27 14:57:11 2017 +0300 Support drag and drop of region by mouse (Bug#26725) * doc/emacs/frames.texi (Drag and Drop): Document support of drag and drop region by mouse. * lisp/mouse.el (mouse-drag-region): Call mouse-drag-and-drop-region when start-event is on region. (mouse-drag-and-drop-region): New function, moves the region by (mouse-drag-and-drop-region): New defcustom. * etc/NEWS: Mention mouse-drag-and-drop-region. diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index 68c12d272f..8984555066 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1074,6 +1074,18 @@ file on a Dired buffer moves or copies the file (according to the conventions of the application it came from) into the directory displayed in that buffer. +@vindex mouse-drag-and-drop-region + Emacs can also optionally drag the region of text by mouse into +another portion of this or another buffer. To enable that, customize +the variable @code{mouse-drag-and-drop-region} to a non-nil value. +Normally, the text is moved, i.e. cut and pasted, when the destination +is the same buffer as the origin; dropping the region on another +buffer copies the text instead. If the value of this variable names a +modifier key, such as @samp{shift} or @samp{control} or @samp{alt}, +then pressing that modifier key when dropping the text will copy it +instead of cutting it, even if you drop on the same buffer as the one +from which the text came. + @vindex dnd-open-file-other-window Dropping a file normally visits it in the window you drop it on. If you prefer to visit the file in a new window in such cases, customize diff --git a/etc/NEWS b/etc/NEWS index 2a7c48d811..60066b7c9f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -169,6 +169,10 @@ keeps point at the end of the region, setting it to non-nil moves point to the beginning of the region. +++ +** The new user option 'mouse-drag-and-drop-region' allows to drag the +entire region of text to another place or another buffer. + ++++ ** The new user option 'confirm-kill-processes' allows the user to skip a confirmation prompt for killing subprocesses when exiting Emacs. When set to t (the default), Emacs will prompt for diff --git a/lisp/mouse.el b/lisp/mouse.el index 0520fd1ab9..9b6b169e56 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -714,12 +714,19 @@ Upon exit, point is at the far edge of the newly visible text." Highlight the drag area as you move the mouse. This must be bound to a button-down mouse event. In Transient Mark mode, the highlighting remains as long as the mark -remains active. Otherwise, it remains until the next input event." - (interactive "e") - ;; Give temporary modes such as isearch a chance to turn off. - (run-hooks 'mouse-leave-buffer-hook) - (mouse-drag-track start-event)) +remains active. Otherwise, it remains until the next input event. +When the region already exists and `mouse-drag-and-drop-region' +is non-nil, this moves the entire region of text to where mouse +is dragged over to." + (interactive "e") + (if (and mouse-drag-and-drop-region + (not (member 'triple (event-modifiers start-event))) + (equal (mouse-posn-property (event-start start-event) 'face) 'region)) + (mouse-drag-and-drop-region start-event) + ;; Give temporary modes such as isearch a chance to turn off. + (run-hooks 'mouse-leave-buffer-hook) + (mouse-drag-track start-event))) (defun mouse-posn-property (pos property) "Look for a property at click position. @@ -1937,6 +1944,84 @@ choose a font." t (called-interactively-p 'interactive))))))))) +;; Drag and drop support. +(defcustom mouse-drag-and-drop-region nil + "If non-nil, dragging the mouse drags the region, if that exists. +If the value is a modifier, such as `control' or `shift' or `meta', +then if that modifier key is pressed when dropping the region, region +text is copied instead of being cut." + :type 'symbol + :version "26.1" + :group 'mouse) + +(defun mouse-drag-and-drop-region (event) + "Move text in the region to point where mouse is dragged to. +The transportation of text is also referred as `drag and drop'. +When text is dragged over to a different buffer, or if a +modifier key was pressed when dropping, and the value of the +variable `mouse-drag-and-drop-region' is that modifier, the text +is copied instead of being cut." + (interactive "e") + (require 'tooltip) + (let ((start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + value-selection) + (track-mouse + ;; When event was click instead of drag, skip loop + (while (progn + (setq event (read-event)) + (mouse-movement-p event)) + (unless value-selection ; initialization + (delete-overlay mouse-secondary-overlay) + (setq value-selection (buffer-substring start end)) + (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) + (ignore-errors (deactivate-mark) ; care existing region in other window + (mouse-set-point event) + (tooltip-show value-selection))) + (tooltip-hide)) + ;; Do not modify buffer under mouse when "event was click", + ;; "drag negligible", or + ;; "drag to read-only". + (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" + (member 'secondary-selection ; "drag negligible" + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at (posn-point (event-end event))))) + buffer-read-only) + ;; Do not modify buffer under mouse. + (cond + ;; "drag negligible" or "drag to read-only", restore region. + (value-selection + (select-window window) ; In case miss drag to other window + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; "event was click" + (t + (deactivate-mark) + (mouse-set-point event))) + ;; Modify buffer under mouse by inserting text. + (push-mark) + (insert value-selection) + (when (not (equal (mark) (point))) ; on success insert + (setq deactivate-mark nil) + (activate-mark)) ; have region on destination + ;; Take care of initial region on source. + (if (equal (current-buffer) buffer) ; when same buffer + (let (deactivate-mark) ; remove text + (unless (member mouse-drag-and-drop-region (event-modifiers event)) + (kill-region (overlay-start mouse-secondary-overlay) + (overlay-end mouse-secondary-overlay)))) + (let ((window1 (selected-window))) ; when beyond buffer + (select-window window) + (goto-char point) ; restore point on source window + (activate-mark) ; restore region + (select-window window1)))) + (delete-overlay mouse-secondary-overlay))) + + ;;; Bindings for mouse commands. (global-set-key [down-mouse-1] 'mouse-drag-region) commit 6f63c7cb6a02d913d195410e4df85fad5832db06 Author: Noam Postavsky Date: Fri May 26 23:26:27 2017 -0400 * lisp/emacs-lisp/eieio.el (defclass): Fix quote in warning message. diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index e21d46e528..1a7de55fce 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -235,7 +235,7 @@ This method is obsolete." (let ((f (intern (format "%s-child-p" name)))) `((defalias ',f ',testsym2) (make-obsolete - ',f ,(format "use (cl-typep ... '%s) instead" name) + ',f ,(format "use (cl-typep ... \\='%s) instead" name) "25.1")))) ;; When using typep, (typep OBJ 'myclass) returns t for objects which commit 0d676deba49ccab9a6a07bc1deeacff51dd44cbf Author: Alan Third Date: Thu May 25 19:23:39 2017 +0100 Check if instancetype supported in ObjC * configure.ac: Add check for instancetype. * src/nsterm.h [!NATIVE_OBJC_INSTANCETYPE]: Define instancetype. diff --git a/configure.ac b/configure.ac index 6d23b5d214..164454dff3 100644 --- a/configure.ac +++ b/configure.ac @@ -1980,6 +1980,25 @@ AC_SUBST(ns_self_contained) AC_SUBST(NS_OBJ) AC_SUBST(NS_OBJC_OBJ) +if test "${HAVE_NS}" = yes; then + AC_CACHE_CHECK( + [if the Objective C compiler supports instancetype], + [emacs_cv_objc_instancetype], + [AC_LANG_PUSH([Objective C]) + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[@interface Test + + (instancetype)test; + @end]])], + emacs_cv_objc_instancetype=yes, + emacs_cv_objc_instancetype=no) + AC_LANG_POP([Objective C])]) + + if test x$emacs_cv_objc_instancetype = xyes ; then + AC_DEFINE(NATIVE_OBJC_INSTANCETYPE, 1, + [Define if ObjC compiler supports instancetype natively.]) + fi +fi + HAVE_W32=no W32_OBJ= W32_LIBS= diff --git a/src/nsterm.h b/src/nsterm.h index 8f3d92b353..f75e3759e4 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -62,15 +62,6 @@ typedef CGFloat EmacsCGFloat; typedef float EmacsCGFloat; #endif -/* FIXME: instancetype is a language built-in, but older versions of - Clang don't support it, and I don't know if GCC supports it at all. - Should this be tested for in ./configure? */ -#if defined (NS_IMPL_GNUSTEP) - || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10 -typedef id instancetype; -typedef NSUInteger NSWindowStyleMask; -#endif - /* ========================================================================== Trace support @@ -365,6 +356,12 @@ char const * nstrace_fullscreen_type_name (int); #endif +/* If the compiler doesn't support instancetype, map it to id. */ +#ifndef NATIVE_OBJC_INSTANCETYPE +typedef id instancetype; +#endif + + /* ========================================================================== NSColor, EmacsColor category. @@ -1302,6 +1299,11 @@ extern char gnustep_base_version[]; /* version tracking */ #define NSWindowStyleMaskUtilityWindow NSUtilityWindowMask #define NSAlertStyleCritical NSCriticalAlertStyle #define NSControlSizeRegular NSRegularControlSize + +/* And adds NSWindowStyleMask. */ +#ifdef __OBJC__ +typedef NSUInteger NSWindowStyleMask; +#endif #endif #endif /* HAVE_NS */ commit dc79aa10f117dea1204634626a5f96a21722807f Author: Wilfred Hughes Date: Fri May 26 22:45:58 2017 +0100 Mark keywordp as a safe, error-free function * lisp/emacs-lisp/byte-opt.el: Add keywordp to side-effect-and-error-free-fns. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 2a240f502c..962a7ae5cd 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1247,7 +1247,7 @@ hash-table-p identity ignore integerp integer-or-marker-p interactive-p invocation-directory invocation-name - keymapp + keymapp keywordp line-beginning-position line-end-position list listp make-marker mark mark-marker markerp max-char memory-limit minibuffer-window commit 4681fbac9061e887e355bf60f87226961db2cb89 Author: Paul Eggert Date: Fri May 26 09:07:50 2017 -0700 * src/inotify.c: Add FIXME comments. diff --git a/src/inotify.c b/src/inotify.c index d43b959747..1165293d24 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -41,21 +41,21 @@ along with GNU Emacs. If not, see . */ #ifndef IN_ONLYDIR # define IN_ONLYDIR 0 #endif + +/* Events that inotify-add-watch waits for. This list has all the + events that any watcher could include, because we want to support + multiple watches on the same file even though inotify uses the same + descriptor for all watches to that file. This list omits + IN_ACCESS, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, and IN_OPEN because + they would prevent other processes from reading; see Bug#26973. + + FIXME: Explain why it is OK to omit these four bits here even + though a inotify-add-watch call might specify them. */ + #define INOTIFY_DEFAULT_MASK \ - (IN_ATTRIB | \ - /* IN_ACCESS | */ \ - /* IN_CLOSE_WRITE | */ \ - /* IN_CLOSE_NOWRITE | */ \ - IN_CREATE | \ - IN_DELETE | \ - IN_DELETE_SELF | \ - IN_IGNORED | \ - IN_MODIFY | \ - IN_MOVE_SELF | \ - IN_MOVED_FROM | \ - IN_MOVED_TO | \ - /* IN_OPEN | */ \ - IN_EXCL_UNLINK) + (IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF \ + | IN_IGNORED | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM \ + | IN_MOVED_TO | IN_EXCL_UNLINK) /* File handle for inotify. */ static int inotifyfd = -1; @@ -74,6 +74,9 @@ static int inotifyfd = -1; IN_ONESHOT IN_ONLYDIR + FIXME: Explain why IN_ONLYDIR is in the list, as it seems to be + in the same category as IN_DONT_FOLLOW which is allowed. + Each element of this list is of the form (DESCRIPTOR . WATCHES) where no two DESCRIPTOR values are the same. DESCRIPTOR represents the inotify watch descriptor and WATCHES is a list with elements of @@ -423,8 +426,8 @@ See inotify(7) and inotify_add_watch(2) for further information. The inotify fd is managed internally and there is no corresponding inotify_init. Use `inotify-rm-watch' to remove a watch. -Also note, that the following inotify bit-masks can not be used, due -to the fact that descriptors are shared across different callers. +The following inotify bit-masks cannot be used because descriptors are +shared across different callers. IN_EXCL_UNLINK IN_MASK_ADD commit d02e8ab6d622546bf5bb6b728644ace7a8f5fc2d Author: Andreas Politz Date: Fri May 26 16:42:43 2017 +0200 Fix Bug#26973 * src/inotify.c (INOTIFY_DEFAULT_MASK): Removing ACCESS, OPEN and CLOSE events on order do let other processes also reading from their descriptors. (Bug#26973). diff --git a/src/inotify.c b/src/inotify.c index 290701349e..d43b959747 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -41,7 +41,21 @@ along with GNU Emacs. If not, see . */ #ifndef IN_ONLYDIR # define IN_ONLYDIR 0 #endif -#define INOTIFY_DEFAULT_MASK (IN_ALL_EVENTS | IN_EXCL_UNLINK) +#define INOTIFY_DEFAULT_MASK \ + (IN_ATTRIB | \ + /* IN_ACCESS | */ \ + /* IN_CLOSE_WRITE | */ \ + /* IN_CLOSE_NOWRITE | */ \ + IN_CREATE | \ + IN_DELETE | \ + IN_DELETE_SELF | \ + IN_IGNORED | \ + IN_MODIFY | \ + IN_MOVE_SELF | \ + IN_MOVED_FROM | \ + IN_MOVED_TO | \ + /* IN_OPEN | */ \ + IN_EXCL_UNLINK) /* File handle for inotify. */ static int inotifyfd = -1; commit b3032988400448ff0ad2f6e658a0e90fac6bd15f Author: Michael Albinus Date: Fri May 26 16:25:18 2017 +0200 Remove Emacs 23 compat code from Tramp * doc/misc/tramp.texi (Remote processes): Don't mention Emacs 24 explicitely. (Frequently Asked Questions): Remove Emacs 23 from compatibility list. * lisp/net/tramp.el: * lisp/net/tramp-adb.el: * lisp/net/tramp-cache.el: * lisp/net/tramp-gvfs.el: * lisp/net/tramp-sh.el: * lisp/net/tramp-smb.el: Replace compat function calls. * lisp/net/tramp-compat.el (remote-file-name-inhibit-cache) (tramp-compat-condition-case-unless-debug) (tramp-compat-copy-file, tramp-compat-copy-directory) (tramp-compat-delete-file, tramp-compat-delete-directory) (tramp-compat-process-live-p): Remove them. * lisp/net/trampver.el: Make version check fit for Emacs 24. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 179578eea9..4ca393256f 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -2553,9 +2553,8 @@ when using @value{tramp} between two hosts with different operating systems, such as @samp{windows-nt} and @samp{gnu/linux}. This option ensures the correct name of the remote shell program. -Starting with Emacs 24, when @option{explicit-shell-file-name} is -equal to @code{nil}, calling @code{shell} interactively will prompt -for a shell name. +When @option{explicit-shell-file-name} is equal to @code{nil}, calling +@code{shell} interactively will prompt for a shell name. Starting with Emacs 26, you could use connection-local variables for setting different values of @option{explicit-shell-file-name} for @@ -2856,8 +2855,7 @@ Where is the latest @value{tramp}? @item Which systems does it work on? -The package works successfully on Emacs 23, Emacs 24, Emacs 25, and -Emacs 26. +The package works successfully on Emacs 24, Emacs 25, and Emacs 26. While Unix and Unix-like systems are the primary remote targets, @value{tramp} has equal success connecting to other platforms, such as diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 1c894c9b0c..a6c2c14212 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -206,7 +206,7 @@ pass to the OPERATION." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) - (while (tramp-compat-process-live-p p) + (while (process-live-p p) (accept-process-output p 0.1)) (accept-process-output p 0.1) (tramp-message v 6 "\n%s" (buffer-string)) @@ -1210,7 +1210,7 @@ connection if a previous connection has died for some reason." (when (and user (not (tramp-get-file-property vec "" "su-command-p" t))) (tramp-error vec 'file-error "Cannot switch to user `%s'" user)) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (save-match-data (when (and p (processp p)) (delete-process p)) (if (zerop (length device)) @@ -1229,7 +1229,7 @@ connection if a previous connection has died for some reason." vec 6 "%s" (mapconcat 'identity (process-command p) " ")) ;; Wait for initial prompt. (tramp-adb-wait-for-output p 30) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (tramp-error vec 'file-error "Terminated!")) (tramp-set-connection-property p "vector" vec) (process-put p 'adjust-window-size-function 'ignore) diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index a9a1c6615e..a863860abf 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -250,7 +250,7 @@ value is not set for the connection, returns DEFAULT." (value ;; If the key is an auxiliary process object, check whether ;; the process is still alive. - (if (and (processp key) (not (tramp-compat-process-live-p key))) + (if (and (processp key) (not (process-live-p key))) default (if (hash-table-p hash) (gethash property hash default) diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index 392a28c59d..c998df814c 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -24,8 +24,7 @@ ;;; Commentary: ;; Tramp's main Emacs version for development is Emacs 26. This -;; package provides compatibility functions for Emacs 23, Emacs 24 and -;; Emacs 25. +;; package provides compatibility functions for Emacs 24 and Emacs 25. ;;; Code: @@ -43,12 +42,6 @@ (require 'trampver) (require 'tramp-loaddefs) -;; `remote-file-name-inhibit-cache' has been introduced with Emacs -;; 24.1. Besides t, nil, and integer, we use also timestamps (as -;; returned by `current-time') internally. -(unless (boundp 'remote-file-name-inhibit-cache) - (defvar remote-file-name-inhibit-cache nil)) - ;; For not existing functions, obsolete functions, or functions with a ;; changed argument list, there are compiler warnings. We want to ;; avoid them in cases we know what we do. @@ -84,22 +77,6 @@ 'file-expand-wildcards 'around 'tramp-advice-file-expand-wildcards) (ad-activate 'file-expand-wildcards)))) -;; `condition-case-unless-debug' is introduced with Emacs 24. -(if (fboundp 'condition-case-unless-debug) - (defalias 'tramp-compat-condition-case-unless-debug - 'condition-case-unless-debug) - (defmacro tramp-compat-condition-case-unless-debug - (var bodyform &rest handlers) - "Like `condition-case' except that it does not catch anything when debugging." - (declare (debug condition-case) (indent 2)) - (let ((bodysym (make-symbol "body"))) - `(let ((,bodysym (lambda () ,bodyform))) - (if debug-on-error - (funcall ,bodysym) - (condition-case ,var - (funcall ,bodysym) - ,@handlers)))))) - (defsubst tramp-compat-temporary-file-directory () "Return name of directory for temporary files. It is the default value of `temporary-file-directory'." @@ -123,103 +100,6 @@ Add the extension of F, if existing." 'temporary-file-directory 'tramp-handle-temporary-file-directory)) -;; PRESERVE-EXTENDED-ATTRIBUTES has been introduced with Emacs 24.1 -;; (as PRESERVE-SELINUX-CONTEXT), and renamed in Emacs 24.3. -(defun tramp-compat-copy-file - (filename newname &optional ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes) - "Like `copy-file' for Tramp files (compat function)." - (cond - (preserve-extended-attributes - (condition-case nil - (tramp-compat-funcall - 'copy-file filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes) - (wrong-number-of-arguments - (copy-file - filename newname ok-if-already-exists keep-date preserve-uid-gid)))) - (t - (copy-file - filename newname ok-if-already-exists keep-date preserve-uid-gid)))) - -;; COPY-CONTENTS has been introduced with Emacs 24.1. -(defun tramp-compat-copy-directory - (directory newname &optional keep-time parents copy-contents) - "Make a copy of DIRECTORY (compat function)." - (condition-case nil - (tramp-compat-funcall - 'copy-directory directory newname keep-time parents copy-contents) - - ;; `copy-directory' is either not implemented, or it does not - ;; support the the COPY-CONTENTS flag. For the time being, we - ;; ignore COPY-CONTENTS as well. - - (error - ;; If `default-directory' is a remote directory, make sure we - ;; find its `copy-directory' handler. - (let ((handler (or (find-file-name-handler directory 'copy-directory) - (find-file-name-handler newname 'copy-directory)))) - (if handler - (funcall handler 'copy-directory directory newname keep-time parents) - - ;; Compute target name. - (setq directory (directory-file-name (expand-file-name directory)) - newname (directory-file-name (expand-file-name newname))) - (if (and (file-directory-p newname) - (not (string-equal (file-name-nondirectory directory) - (file-name-nondirectory newname)))) - (setq newname - (expand-file-name - (file-name-nondirectory directory) newname))) - (if (not (file-directory-p newname)) (make-directory newname parents)) - - ;; Copy recursively. - (mapc - (lambda (file) - (if (file-directory-p file) - (tramp-compat-copy-directory file newname keep-time parents) - (copy-file file newname t keep-time))) - ;; We do not want to delete "." and "..". - (directory-files directory 'full directory-files-no-dot-files-regexp)) - - ;; Set directory attributes. - (set-file-modes newname (file-modes directory)) - (if keep-time - (set-file-times newname (nth 5 (file-attributes directory))))))))) - -;; TRASH has been introduced with Emacs 24.1. -(defun tramp-compat-delete-file (filename &optional trash) - "Like `delete-file' for Tramp files (compat function)." - (condition-case nil - (tramp-compat-funcall 'delete-file filename trash) - ;; This Emacs version does not support the TRASH flag. - (wrong-number-of-arguments - (let ((delete-by-moving-to-trash (and delete-by-moving-to-trash trash))) - (delete-file filename))))) - -;; RECURSIVE has been introduced with Emacs 23.2. TRASH has been -;; introduced with Emacs 24.1. -(defun tramp-compat-delete-directory (directory &optional recursive trash) - "Like `delete-directory' for Tramp files (compat function)." - (condition-case nil - (cond - (trash - (tramp-compat-funcall 'delete-directory directory recursive trash)) - (t - (delete-directory directory recursive))) - ;; This Emacs version does not support the TRASH flag. We use the - ;; implementation from Emacs 23.2. - (wrong-number-of-arguments - (setq directory (directory-file-name (expand-file-name directory))) - (when (not (file-symlink-p directory)) - (mapc (lambda (file) - (if (eq t (car (file-attributes file))) - (tramp-compat-delete-directory file recursive trash) - (tramp-compat-delete-file file trash))) - (directory-files - directory 'full directory-files-no-dot-files-regexp))) - (delete-directory directory)))) - (defun tramp-compat-process-running-p (process-name) "Returns t if system process PROCESS-NAME is running for `user-login-name'." (when (stringp process-name) @@ -244,19 +124,6 @@ Add the extension of F, if existing." process-name)))) (setq result t))))))))) -;; `process-running-live-p' is introduced in Emacs 24. -(defalias 'tramp-compat-process-live-p - (if (fboundp 'process-running-live-p) - 'process-running-live-p - (lambda (process) - "Returns non-nil if PROCESS is alive. -A process is considered alive if its status is `run', `open', -`listen', `connect' or `stop'. Value is nil if PROCESS is not a -process." - (and (processp process) - (memq (process-status process) - '(run open listen connect stop)))))) - ;; `user-error' has appeared in Emacs 24.3. (defsubst tramp-compat-user-error (vec-or-proc format &rest args) "Signal a pilot error." @@ -323,15 +190,15 @@ This is a floating point number if the size is too large for an integer." This is a string of ten letters or dashes as in ls -l." (nth 8 attributes))) -;; `default-toplevel-value' has been declared in Emacs 24. +;; `default-toplevel-value' has been declared in Emacs 24.4. (unless (fboundp 'default-toplevel-value) (defalias 'default-toplevel-value 'symbol-value)) -;; `format-message' is new in Emacs 25. +;; `format-message' is new in Emacs 25.1. (unless (fboundp 'format-message) (defalias 'format-message 'format)) -;; `file-missing' is introduced in Emacs 26. +;; `file-missing' is introduced in Emacs 26.1. (defconst tramp-file-missing (if (get 'file-missing 'error-conditions) 'file-missing 'file-error) "The error symbol for the `file-missing' error.") diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 57a135139a..c016c7e027 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -39,7 +39,7 @@ ;; All actions to mount a remote location, and to retrieve mount ;; information, are performed by D-Bus messages. File operations ;; themselves are performed via the mounted filesystem in ~/.gvfs. -;; Consequently, GNU Emacs 23.1 with enabled D-Bus bindings is a +;; Consequently, GNU Emacs with enabled D-Bus bindings is a ;; precondition. ;; The GVFS D-Bus interface is said to be unstable. There were even @@ -158,7 +158,6 @@ (defconst tramp-gvfs-service-daemon "org.gtk.vfs.Daemon" "The well known name of the GVFS daemon.") -;; D-Bus integration is available since Emacs 23 on some system types. ;; We don't call `dbus-ping', because this would load dbus.el. (defconst tramp-gvfs-enabled (ignore-errors @@ -666,19 +665,10 @@ file names." (and t2 (not (tramp-gvfs-file-name-p newname)))) ;; We cannot copy or rename directly. - ;; PRESERVE-EXTENDED-ATTRIBUTES has been introduced with - ;; Emacs 24.1 (as PRESERVE-SELINUX-CONTEXT), and renamed - ;; in Emacs 24.3. (let ((tmpfile (tramp-compat-make-temp-file filename))) - (cond - (preserve-extended-attributes - (funcall - file-operation - filename tmpfile t keep-date preserve-uid-gid - preserve-extended-attributes)) - (t - (funcall - file-operation filename tmpfile t keep-date preserve-uid-gid))) + (funcall + file-operation filename tmpfile t keep-date preserve-uid-gid + preserve-extended-attributes) (rename-file tmpfile newname ok-if-already-exists)) ;; Direct action. @@ -729,25 +719,16 @@ file names." "Like `copy-file' for Tramp files." (setq filename (expand-file-name filename)) (setq newname (expand-file-name newname)) - (cond - ;; At least one file a Tramp file? - ((or (tramp-tramp-file-p filename) - (tramp-tramp-file-p newname)) - (tramp-gvfs-do-copy-or-rename-file - 'copy filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes)) - ;; Compat section. PRESERVE-EXTENDED-ATTRIBUTES has been - ;; introduced with Emacs 24.1 (as PRESERVE-SELINUX-CONTEXT), and - ;; renamed in Emacs 24.3. - (preserve-extended-attributes + ;; At least one file a Tramp file? + (if (or (tramp-tramp-file-p filename) + (tramp-tramp-file-p newname)) + (tramp-gvfs-do-copy-or-rename-file + 'copy filename newname ok-if-already-exists keep-date + preserve-uid-gid preserve-extended-attributes) (tramp-run-real-handler 'copy-file (list filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes))) - (t - (tramp-run-real-handler - 'copy-file - (list filename newname ok-if-already-exists keep-date preserve-uid-gid))))) + preserve-uid-gid preserve-extended-attributes)))) (defun tramp-gvfs-handle-delete-directory (directory &optional recursive trash) "Like `delete-directory' for Tramp files." @@ -756,8 +737,8 @@ file names." (mapc (lambda (file) (if (eq t (tramp-compat-file-attribute-type (file-attributes file))) - (tramp-compat-delete-directory file recursive trash) - (tramp-compat-delete-file file trash))) + (delete-directory file recursive trash) + (delete-file file trash))) (directory-files directory 'full directory-files-no-dot-files-regexp)) (when (directory-files directory nil directory-files-no-dot-files-regexp) @@ -1089,7 +1070,7 @@ file names." ;; There might be an error if the monitor is not supported. ;; Give the filter a chance to read the output. (tramp-accept-process-output p 1) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (tramp-error v 'file-notify-error "Monitoring not supported for `%s'" file-name)) p)))) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 84782a4c7f..2541fcf551 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1303,13 +1303,7 @@ target of the symlink differ." (when (> (buffer-size) 0) (goto-char (point-min)) ;; ... inode - (setq res-inode - (condition-case err - (read (current-buffer)) - ;; This error happens in Emacs 23. Starting with - ;; Emacs 24, a large integer will be converted into - ;; a float automatically during `read'. - (overflow-error (string-to-number (cadr err))))) + (setq res-inode (read (current-buffer))) ;; ... file mode flags (setq res-filemodes (symbol-name (read (current-buffer)))) ;; ... number links @@ -1950,27 +1944,17 @@ tramp-sh-handle-file-name-all-completions: internal error accessing `%s': `%s'" (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid preserve-extended-attributes) "Like `copy-file' for Tramp files." - (setq filename (expand-file-name filename)) - (setq newname (expand-file-name newname)) - (cond - ;; At least one file a Tramp file? - ((or (tramp-tramp-file-p filename) - (tramp-tramp-file-p newname)) - (tramp-do-copy-or-rename-file - 'copy filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes)) - ;; Compat section. PRESERVE-EXTENDED-ATTRIBUTES has been - ;; introduced with Emacs 24.1 (as PRESERVE-SELINUX-CONTEXT), and - ;; renamed in Emacs 24.3. - (preserve-extended-attributes + (setq filename (expand-file-name filename) + newname (expand-file-name newname)) + (if (or (tramp-tramp-file-p filename) + (tramp-tramp-file-p newname)) + (tramp-do-copy-or-rename-file + 'copy filename newname ok-if-already-exists keep-date + preserve-uid-gid preserve-extended-attributes) (tramp-run-real-handler 'copy-file (list filename newname ok-if-already-exists keep-date - preserve-uid-gid preserve-extended-attributes))) - (t - (tramp-run-real-handler - 'copy-file - (list filename newname ok-if-already-exists keep-date preserve-uid-gid))))) + preserve-uid-gid preserve-extended-attributes)))) (defun tramp-sh-handle-copy-directory (dirname newname &optional keep-date parents copy-contents) @@ -2814,7 +2798,7 @@ the result will be a local, non-Tramp, file name." (defun tramp-process-sentinel (proc event) "Flush file caches." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (let ((vec (tramp-get-connection-property proc "vector" nil))) (when vec (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event) @@ -3628,7 +3612,7 @@ Fall back to normal file name handler if no Tramp handler exists." ;; There might be an error if the monitor is not supported. ;; Give the filter a chance to read the output. (tramp-accept-process-output p 1) - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) (tramp-error v 'file-notify-error "Monitoring not supported for `%s'" file-name)) p)))) @@ -4620,7 +4604,7 @@ connection if a previous connection has died for some reason." ;; If Tramp opens the same connection within a short time frame, ;; there is a problem. We shall signal this. - (unless (or (tramp-compat-process-live-p p) + (unless (or (process-live-p p) (not (tramp-file-name-equal-p vec (car tramp-current-connection))) (> (tramp-time-diff @@ -4641,9 +4625,9 @@ connection if a previous connection has died for some reason." (tramp-get-connection-property p "last-cmd-time" '(0 0 0))) 60) - (tramp-compat-process-live-p p)) + (process-live-p p)) (tramp-send-command vec "echo are you awake" t t) - (unless (and (tramp-compat-process-live-p p) + (unless (and (process-live-p p) (tramp-wait-for-output p 10)) ;; The error will be caught locally. (tramp-error vec 'file-error "Awake did fail"))) @@ -4653,7 +4637,7 @@ connection if a previous connection has died for some reason." ;; New connection must be opened. (condition-case err - (unless (tramp-compat-process-live-p p) + (unless (process-live-p p) ;; During completion, don't reopen a new connection. We ;; check this for the process related to diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 88db8eaf0e..9ac2fc6670 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -382,7 +382,7 @@ pass to the OPERATION." (defun tramp-smb-action-with-tar (proc vec) "Untar from connection buffer." - (if (not (tramp-compat-process-live-p proc)) + (if (not (process-live-p proc)) (throw 'tramp-action 'process-died) (with-current-buffer (tramp-get-connection-buffer vec) @@ -516,7 +516,7 @@ pass to the OPERATION." (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-with-tar) - (while (tramp-compat-process-live-p p) + (while (process-live-p p) (sit-for 0.1)) (tramp-message v 6 "\n%s" (buffer-string)))) @@ -561,7 +561,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." 0 (format "Copying %s to %s" filename newname) (if (file-directory-p filename) - (tramp-compat-copy-directory + (copy-directory filename newname keep-date 'parents 'copy-contents) (let ((tmpfile (file-local-copy filename))) @@ -708,7 +708,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (defun tramp-smb-action-get-acl (proc vec) "Read ACL data from connection buffer." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) ;; Accept pending output. (while (tramp-accept-process-output proc 0.1)) (with-current-buffer (tramp-get-connection-buffer vec) @@ -1224,7 +1224,7 @@ target of the symlink differ." (narrow-to-region (point-max) (point-max)) (let ((p (tramp-get-connection-process v))) (tramp-smb-send-command v "exit $lasterrorcode") - (while (tramp-compat-process-live-p p) + (while (process-live-p p) (sleep-for 0.1) (setq ret (process-exit-status p)))) (delete-region (point-min) (point-max)) @@ -1308,7 +1308,7 @@ target of the symlink differ." (defun tramp-smb-action-set-acl (proc vec) "Read ACL data from connection buffer." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) ;; Accept pending output. (while (tramp-accept-process-output proc 0.1)) (with-current-buffer (tramp-get-connection-buffer vec) @@ -1724,7 +1724,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." (defun tramp-smb-get-cifs-capabilities (vec) "Check, whether the SMB server supports POSIX commands." ;; When we are not logged in yet, we return nil. - (if (tramp-compat-process-live-p (tramp-get-connection-process vec)) + (if (process-live-p (tramp-get-connection-process vec)) (with-tramp-connection-property (tramp-get-connection-process vec) "cifs-capabilities" (save-match-data @@ -1742,7 +1742,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." "Check, whether the SMB server supports the STAT command." ;; When we are not logged in yet, we return nil. (if (and (tramp-smb-get-share vec) - (tramp-compat-process-live-p (tramp-get-connection-process vec))) + (process-live-p (tramp-get-connection-process vec))) (with-tramp-connection-property (tramp-get-connection-process vec) "stat-capability" (tramp-smb-send-command vec "stat \"/\"")))) @@ -1807,13 +1807,13 @@ If ARGUMENT is non-nil, use it as argument for (tramp-get-connection-property p "last-cmd-time" '(0 0 0))) 60) - (tramp-compat-process-live-p p) + (process-live-p p) (re-search-forward tramp-smb-errors nil t)) (delete-process p) (setq p nil))) ;; Check whether it is still the same share. - (unless (and (tramp-compat-process-live-p p) + (unless (and (process-live-p p) (or argument (string-equal share @@ -1949,7 +1949,7 @@ Returns nil if an error message has appeared." ;; Algorithm: get waiting output. See if last line contains ;; `tramp-smb-prompt' sentinel or `tramp-smb-errors' strings. ;; If not, wait a bit and again get waiting output. - (while (and (not found) (not err) (tramp-compat-process-live-p p)) + (while (and (not found) (not err) (process-live-p p)) ;; Accept pending output. (tramp-accept-process-output p 0.1) @@ -1963,7 +1963,7 @@ Returns nil if an error message has appeared." (setq err (re-search-forward tramp-smb-errors nil t))) ;; When the process is still alive, read pending output. - (while (and (not found) (tramp-compat-process-live-p p)) + (while (and (not found) (process-live-p p)) ;; Accept pending output. (tramp-accept-process-output p 0.1) @@ -1987,7 +1987,7 @@ Returns nil if an error message has appeared." "Send SIGKILL to the winexe process." (ignore-errors (let ((p (get-buffer-process (current-buffer)))) - (when (tramp-compat-process-live-p p) + (when (process-live-p p) (signal-process (process-id p) 'SIGINT))))) (defun tramp-smb-call-winexe (vec) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index a1cd90bec7..e75305b637 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -35,7 +35,7 @@ ;; Notes: ;; ----- ;; -;; This package only works for Emacs 23.1 and higher. +;; This package only works for Emacs 24.1 and higher. ;; ;; Also see the todo list at the bottom of this file. ;; @@ -555,7 +555,8 @@ The `sudo' program appears to insert a `^@' character into the prompt." "Sorry, try again." "Name or service not known" "Host key verification failed." - "No supported authentication methods left to try!") t) + "No supported authentication methods left to try!") + t) ".*" "\\|" "^.*\\(" @@ -1502,7 +1503,6 @@ ARGUMENTS to actually emit the message (if applicable)." "^" (regexp-opt '("tramp-backtrace" - "tramp-compat-condition-case-unless-debug" "tramp-compat-funcall" "tramp-compat-user-error" "tramp-condition-case-unless-debug" @@ -1691,16 +1691,14 @@ without a visible progress reporter." (tramp-message ,vec ,level "%s..." ,message) (let ((cookie "failed") (tm - ;; We start a pulsing progress reporter after 3 seconds. Feature - ;; introduced in Emacs 24.1. + ;; We start a pulsing progress reporter after 3 seconds. (when (and tramp-message-show-message ;; Display only when there is a minimum level. (<= ,level (min tramp-verbose 3))) - (ignore-errors - (let ((pr (make-progress-reporter ,message nil nil))) - (when pr - (run-at-time - 3 0.1 #'tramp-progress-reporter-update pr))))))) + (let ((pr (make-progress-reporter ,message nil nil))) + (when pr + (run-at-time + 3 0.1 #'tramp-progress-reporter-update pr)))))) (unwind-protect ;; Execute the body. (prog1 (progn ,@body) (setq cookie "done")) @@ -1913,7 +1911,7 @@ value of `default-file-modes', without execute permissions." "Replace environment variables in FILENAME. Return the string with the replaced variables." (or (ignore-errors - ;; Optional arg has been introduced with Emacs 24 (?). + ;; Optional arg has been introduced with Emacs 24.4. (tramp-compat-funcall 'substitute-env-vars filename 'only-defined)) ;; We need an own implementation. (save-match-data @@ -1974,22 +1972,21 @@ ARGS are the arguments OPERATION has been called with." '(access-file byte-compiler-base-file-name delete-directory delete-file diff-latest-backup-file directory-file-name directory-files directory-files-and-attributes - dired-compress-file dired-uncache + dired-compress-file dired-uncache file-acl file-accessible-directory-p file-attributes file-directory-p file-executable-p file-exists-p - file-local-copy file-modes - file-name-as-directory file-name-directory - file-name-nondirectory file-name-sans-versions + file-local-copy file-modes file-name-as-directory + file-name-directory file-name-nondirectory + file-name-sans-versions file-notify-add-watch file-ownership-preserved-p file-readable-p - file-regular-p file-remote-p file-symlink-p file-truename - file-writable-p find-backup-file-name find-file-noselect - get-file-buffer insert-directory insert-file-contents - load make-directory make-directory-internal - set-file-modes set-file-times substitute-in-file-name - unhandled-file-name-directory vc-registered - ;; Emacs 24+ only. - file-acl file-notify-add-watch file-selinux-context - set-file-acl set-file-selinux-context + file-regular-p file-remote-p file-selinux-context + file-symlink-p file-truename file-writable-p + find-backup-file-name find-file-noselect get-file-buffer + insert-directory insert-file-contents load + make-directory make-directory-internal set-file-acl + set-file-modes set-file-selinux-context set-file-times + substitute-in-file-name unhandled-file-name-directory + vc-registered ;; Emacs 26+ only. file-name-case-insensitive-p)) (if (file-name-absolute-p (nth 0 args)) @@ -1998,10 +1995,9 @@ ARGS are the arguments OPERATION has been called with." ;; FILE DIRECTORY resp FILE1 FILE2. ((member operation '(add-name-to-file copy-directory copy-file expand-file-name + file-equal-p file-in-directory-p file-name-all-completions file-name-completion - file-newer-than-file-p make-symbolic-link rename-file - ;; Emacs 24+ only. - file-equal-p file-in-directory-p)) + file-newer-than-file-p make-symbolic-link rename-file)) (save-match-data (cond ((tramp-tramp-file-p (nth 0 args)) (nth 0 args)) @@ -2026,8 +2022,7 @@ ARGS are the arguments OPERATION has been called with." default-directory) ;; PROC. ((member operation - '(;; Emacs 24+ only. - file-notify-rm-watch + '(file-notify-rm-watch ;; Emacs 25+ only. file-notify-valid-p)) (when (processp (nth 0 args)) @@ -2056,7 +2051,7 @@ ARGS are the arguments OPERATION has been called with." (var bodyform &rest handlers) "Like `condition-case-unless-debug' but `tramp-debug-on-error'." `(let ((debug-on-error tramp-debug-on-error)) - (tramp-compat-condition-case-unless-debug ,var ,bodyform ,@handlers))) + (condition-case-unless-debug ,var ,bodyform ,@handlers))) ;; Main function. (defun tramp-file-name-handler (operation &rest args) @@ -2308,8 +2303,8 @@ Add operations defined in `HANDLER-alist' to `tramp-file-name-handler'." (defun tramp-completion-mode-p () "Check, whether method / user name / host name completion is active." (or - ;; Signal from outside. `non-essential' has been introduced in Emacs 24. - (bound-and-true-p non-essential) + ;; Signal from outside. + non-essential ;; This variable has been obsoleted in Emacs 26. tramp-completion-mode)) @@ -2320,7 +2315,7 @@ not in completion mode." (let (tramp-verbose) (and (tramp-tramp-file-p filename) (or (not (tramp-completion-mode-p)) - (tramp-compat-process-live-p + (process-live-p (tramp-get-connection-process (tramp-dissect-file-name filename))))))) @@ -2986,7 +2981,7 @@ User is always nil." (when (tramp-tramp-file-p filename) (let* ((v (tramp-dissect-file-name filename)) (p (tramp-get-connection-process v)) - (c (and (tramp-compat-process-live-p p) + (c (and (process-live-p p) (tramp-get-connection-property p "connected" nil)))) ;; We expand the file name only, if there is already a connection. (with-parsed-tramp-file-name @@ -3399,7 +3394,7 @@ of." (defun tramp-handle-file-notify-valid-p (proc) "Like `file-notify-valid-p' for Tramp files." - (and (tramp-compat-process-live-p proc) + (and (process-live-p proc) ;; Sometimes, the process is still in status `run' when the ;; file or directory to be watched is deleted already. (with-current-buffer (process-buffer proc) @@ -3494,14 +3489,14 @@ The terminal type can be configured with `tramp-terminal-type'." (defun tramp-action-process-alive (proc _vec) "Check, whether a process has finished." - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (throw 'tramp-action 'process-died))) (defun tramp-action-out-of-band (proc vec) "Check, whether an out-of-band copy has finished." ;; There might be pending output for the exit status. (tramp-accept-process-output proc 0.1) - (cond ((and (not (tramp-compat-process-live-p proc)) + (cond ((and (not (process-live-p proc)) (zerop (process-exit-status proc))) (tramp-message vec 3 "Process has finished.") (throw 'tramp-action 'ok)) @@ -3614,7 +3609,7 @@ for process communication also." (lambda (key _value) (and (processp key) (not (string-prefix-p "*tramp/" (process-name key))) - (tramp-compat-process-live-p key) + (process-live-p key) (setq result t))) tramp-cache-data) result)) @@ -3678,14 +3673,14 @@ nil." (with-timeout (timeout) (while (not found) (tramp-accept-process-output proc 1) - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (tramp-error-with-buffer nil proc 'file-error "Process has died")) (setq found (tramp-check-for-regexp proc regexp))))) (t (while (not found) (tramp-accept-process-output proc 1) - (unless (tramp-compat-process-live-p proc) + (unless (process-live-p proc) (tramp-error-with-buffer nil proc 'file-error "Process has died")) (setq found (tramp-check-for-regexp proc regexp))))) @@ -4221,32 +4216,25 @@ Invokes `password-read' if available, `read-passwd' else." (prog1 (or ;; See if auth-sources contains something useful. - ;; `auth-source-user-or-password' is an obsoleted - ;; function since Emacs 24.1, it has been replaced by - ;; `auth-source-search'. (ignore-errors (and (tramp-get-connection-property v "first-password-request" nil) ;; Try with Tramp's current method. - (if (fboundp 'auth-source-search) - (setq auth-info - (auth-source-search - :max 1 - (and tramp-current-user :user) - tramp-current-user - :host tramp-current-host - :port tramp-current-method - :require - (cons - :secret (and tramp-current-user '(:user)))) - auth-passwd (plist-get - (nth 0 auth-info) :secret) - auth-passwd (if (functionp auth-passwd) - (funcall auth-passwd) - auth-passwd)) - (tramp-compat-funcall - 'auth-source-user-or-password - "password" tramp-current-host tramp-current-method)))) + (setq auth-info + (auth-source-search + :max 1 + (and tramp-current-user :user) + tramp-current-user + :host tramp-current-host + :port tramp-current-method + :require + (cons + :secret (and tramp-current-user '(:user)))) + auth-passwd (plist-get + (nth 0 auth-info) :secret) + auth-passwd (if (functionp auth-passwd) + (funcall auth-passwd) + auth-passwd)))) ;; Try the password cache. (let ((password (password-read pw-prompt key))) (password-cache-add key password) @@ -4275,13 +4263,8 @@ Invokes `password-read' if available, `read-passwd' else." (replace-regexp-in-string (concat tramp-postfix-hop-regexp "$") (tramp-postfix-host-format) hop))))) - ;; `auth-source-forget-user-or-password' is an obsoleted function - ;; since Emacs 24.1, it has been replaced by `auth-source-forget'. - (if (fboundp 'auth-source-forget) - (auth-source-forget - `(:max 1 ,(and user :user) ,user :host ,host :port ,method)) - (tramp-compat-funcall - 'auth-source-forget-user-or-password "password" host method)) + (auth-source-forget + `(:max 1 ,(and user :user) ,user :host ,host :port ,method)) (password-cache-remove (tramp-make-tramp-file-name method user domain host port "")))) diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index e770ecc5a7..387a3c8bb3 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -53,7 +53,7 @@ (replace-regexp-in-string "\n" "" (buffer-string)))))))) ;; Check for Emacs version. -(let ((x (if (>= emacs-major-version 23) +(let ((x (if (>= emacs-major-version 24) "ok" (format "Tramp 2.3.2-pre is not fit for %s" (when (string-match "^.*$" (emacs-version)) commit 4de0737c9b5ae8939763ad70085f02e1eace4032 Author: Katsumi Yamaoka Date: Fri May 26 08:07:58 2017 +0000 Work for application/x-tar-gz and image/svg+xml ;; Try inlining the attachment in the article <87wp94dzj6.fsf@gmail.com> ;; of bug#27078 in the Emacs bug list using Gnus. * lisp/gnus/mm-archive.el (mm-archive-decoders): Add a decoder for application/x-tar-gz. (mm-dissect-archive): Error out if a decoder is not found. * lisp/gnus/mm-decode.el (mm-get-image): Allow image/svg+xml. diff --git a/lisp/gnus/mm-archive.el b/lisp/gnus/mm-archive.el index 5ac8761f6b..103cc89c35 100644 --- a/lisp/gnus/mm-archive.el +++ b/lisp/gnus/mm-archive.el @@ -30,15 +30,18 @@ '(("application/ms-tnef" t "tnef" "-f" "-" "-C") ("application/zip" nil "unzip" "-j" "-x" "%f" "-d") ("application/x-gtar-compressed" nil "tar" "xzf" "-" "-C") + ("application/x-tar-gz" nil "tar" "xzf" "-" "-C") ("application/x-tar" nil "tar" "xf" "-" "-C"))) (defun mm-archive-decoders () mm-archive-decoders) (defun mm-dissect-archive (handle) - (let ((decoder (cddr (assoc (car (mm-handle-type handle)) - mm-archive-decoders))) - (dir (make-temp-file - (expand-file-name "emm." mm-tmp-directory) 'dir))) + (let* ((type (car (mm-handle-type handle))) + (decoder (cddr (assoc type mm-archive-decoders))) + dir) + (unless decoder + (error "No decoder found for %s" type)) + (setq dir (make-temp-file (expand-file-name "emm." mm-tmp-directory) 'dir)) (set-file-modes dir #o700) (unwind-protect (progn diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el index 5b8aeb3ca3..c6a0be36c4 100644 --- a/lisp/gnus/mm-decode.el +++ b/lisp/gnus/mm-decode.el @@ -1555,6 +1555,8 @@ be determined." "xbm") ((equal type "x-portable-bitmap") "pbm") + ((equal type "svg+xml") + "svg") (t type))) (or (mm-handle-cache handle) (mm-with-unibyte-buffer commit 4c4a1b3217570dd306c7ad3ee273a9317ab29134 Author: Tino Calancha Date: Fri May 26 10:59:19 2017 +0900 test-calc-23889: Skip test on 32-bit platforms This test fails on some 32-bit platforms as mentioned in https://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00737.html * test/lisp/calc/calc-tests.el (test-calc-23889): Skip when the Lisp integer is not big enough. diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el index 68567dcc21..e4b43357a0 100644 --- a/test/lisp/calc/calc-tests.el +++ b/test/lisp/calc/calc-tests.el @@ -88,6 +88,7 @@ An existing calc stack is reused, otherwise a new one is created." (ert-deftest test-calc-23889 () "Test for http://debbugs.gnu.org/23889 and 25652." + (skip-unless (>= math-bignum-digit-length 9)) (dolist (mode '(deg rad)) (let ((calc-angle-mode mode)) ;; If user inputs angle units, then should ignore `calc-angle-mode'. commit 2ea4b84f5ee41e633430eef6b4a907dd8d0ce2ed Author: Alan Third Date: Thu May 25 20:13:21 2017 +0100 Fix NS tooltips showing in the wrong place (bug#27053) * src/nsfns.m (compute_tip_xy): Get current mouse position instead of last recorded position. diff --git a/src/nsfns.m b/src/nsfns.m index 3833ee75ac..a69e44bb22 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2729,8 +2729,6 @@ and GNUstep implementations ("distributor-specific release int *root_y) { Lisp_Object left, top, right, bottom; - EmacsView *view = FRAME_NS_VIEW (f); - struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); NSPoint pt; NSScreen *screen; @@ -2742,22 +2740,7 @@ and GNUstep implementations ("distributor-specific release if ((!INTEGERP (left) && !INTEGERP (right)) || (!INTEGERP (top) && !INTEGERP (bottom))) - { - pt.x = dpyinfo->last_mouse_motion_x; - pt.y = dpyinfo->last_mouse_motion_y; - /* Convert to screen coordinates */ - pt = [view convertPoint: pt toView: nil]; -#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 - pt = [[view window] convertBaseToScreen: pt]; -#else - { - NSRect r = NSMakeRect (pt.x, pt.y, 0, 0); - r = [[view window] convertRectToScreen: r]; - pt.x = r.origin.x; - pt.y = r.origin.y; - } -#endif - } + pt = [NSEvent mouseLocation]; else { /* Absolute coordinates. */ commit 9fb9e4b284aaf75f206e875c3fb4da8fa6085d93 Author: Thomas Fitzsimmons Date: Wed May 24 14:34:13 2017 -0400 lisp/net/soap-client.el: Bump version to 3.1.2 * lisp/net/soap-client.el: Bump version to 3.1.2. diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el index 0efbccd265..4ec8a504fb 100644 --- a/lisp/net/soap-client.el +++ b/lisp/net/soap-client.el @@ -5,7 +5,7 @@ ;; Author: Alexandru Harsanyi ;; Author: Thomas Fitzsimmons ;; Created: December, 2009 -;; Version: 3.1.1 +;; Version: 3.1.2 ;; Keywords: soap, web-services, comm, hypermedia ;; Package: soap-client ;; Homepage: https://github.com/alex-hhh/emacs-soap-client commit 4fa8336b033c706ca4c635983bec1ce87df7d184 Author: Thomas Fitzsimmons Date: Wed May 24 15:01:01 2017 -0400 Fix soap-inspect.el doc strings * lisp/net/soap-inspect.el (soap-inspect-xs-attribute): Fix doc string. (soap-inspect-xs-attribute-group): Likewise. diff --git a/lisp/net/soap-inspect.el b/lisp/net/soap-inspect.el index cd14eddb4f..2516bc9924 100644 --- a/lisp/net/soap-inspect.el +++ b/lisp/net/soap-inspect.el @@ -296,8 +296,8 @@ entire WSDL can be inspected." (pp (soap-sample-value element) (current-buffer))) (defun soap-inspect-xs-attribute (attribute) - "Insert information about ATTRIBUTE, a soap-xs-attribute, in -the current buffer." + "Insert information about ATTRIBUTE in the current buffer. +ATTRIBUTE is a soap-xs-attribute." (insert "Attribute: " (soap-element-fq-name attribute)) (insert "\nType: ") (soap-insert-describe-button (soap-xs-attribute-type attribute)) @@ -305,8 +305,8 @@ the current buffer." (pp (soap-sample-value attribute) (current-buffer))) (defun soap-inspect-xs-attribute-group (attribute-group) - "Insert information about ATTRIBUTE-GROUP, a -soap-xs-attribute-group, in the current buffer." + "Insert information about ATTRIBUTE-GROUP in the current buffer. +ATTRIBUTE is a soap-xs-attribute-group." (insert "Attribute group: " (soap-element-fq-name attribute-group)) (insert "\nSample values:\n") (pp (soap-sample-value attribute-group) (current-buffer))) commit a928cfae6046066180a445fab387bb1a57f8395c Author: Thomas Fitzsimmons Date: Wed May 24 14:58:47 2017 -0400 Fix two soap-client.el byte compilation warnings * lisp/net/soap-client.el (url-http-response-status): Add defvar. (soap-fetch-xml-from-url): Remove special declaration of url-http-response-status. (soap-invoke-internal): Likewise. diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el index e204b8aff9..0efbccd265 100644 --- a/lisp/net/soap-client.el +++ b/lisp/net/soap-client.el @@ -2336,6 +2336,8 @@ traverse an element tree." (kill-buffer) (mm-destroy-part mime-part))))) +(defvar url-http-response-status) + (defun soap-fetch-xml-from-url (url wsdl) "Load an XML document from URL and return it. The previously parsed URL is read from WSDL." @@ -2349,7 +2351,6 @@ The previously parsed URL is read from WSDL." (setf (soap-wsdl-current-file wsdl) current-file) (let ((buffer (url-retrieve-synchronously current-file))) (with-current-buffer buffer - (declare (special url-http-response-status)) (if (> url-http-response-status 299) (error "Error retrieving WSDL: %s" url-http-response-status)) (soap-parse-server-response))))) @@ -3073,7 +3074,6 @@ OPERATION-NAME and PARAMETERS are as described in `soap-invoke'." (soap-port-service-url port)))) (condition-case err (with-current-buffer buffer - (declare (special url-http-response-status)) (if (null url-http-response-status) (error "No HTTP response from server")) (if (and soap-debug (> url-http-response-status 299)) commit 9a6ac2794f6855c3f5882d33deb417aa69e7c471 Author: Thomas Fitzsimmons Date: Wed May 24 14:32:00 2017 -0400 lisp/net/soap-client.el: Require cl-lib version 0.6.1 * lisp/net/soap-client.el: Require cl-lib version 0.6.1. diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el index 48cf6ec62f..e204b8aff9 100644 --- a/lisp/net/soap-client.el +++ b/lisp/net/soap-client.el @@ -9,7 +9,7 @@ ;; Keywords: soap, web-services, comm, hypermedia ;; Package: soap-client ;; Homepage: https://github.com/alex-hhh/emacs-soap-client -;; Package-Requires: ((cl-lib "0.5")) +;; Package-Requires: ((cl-lib "0.6.1")) ;; This file is part of GNU Emacs. commit 27cafd13683d6a33abbf08e4f32401b51e70f349 Author: Thomas Fitzsimmons Date: Wed May 24 14:28:32 2017 -0400 lisp/net/soap-client.el: Shorten some long lines * lisp/net/soap-client.el (soap-encode-xs-element): Remove unnecessary progn. (soap-xs-add-union): Wrap long line. Co-authored-by: Stefan Monnier diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el index 922f698576..48cf6ec62f 100644 --- a/lisp/net/soap-client.el +++ b/lisp/net/soap-client.el @@ -895,9 +895,8 @@ This is a specialization of `soap-encode-value' for (setf (soap-xs-element-type^ new-element) (soap-xs-complex-type-base type)) (cl-loop for i below (length value) - do (progn - (soap-encode-xs-element (aref value i) new-element) - ))) + do (soap-encode-xs-element + (aref value i) new-element))) (soap-encode-value value type)) (insert "\n")) ;; else @@ -1163,7 +1162,8 @@ See also `soap-wsdl-resolve-references'." "Add union members defined in XML NODE to TYPE, an `soap-xs-simple-type'." (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:union) nil - "expecting xsd:union node, got %s" (soap-l2wk (xml-node-name node))) + "expecting xsd:union node, got %s" + (soap-l2wk (xml-node-name node))) (setf (soap-xs-simple-type-base type) (mapcar 'soap-l2fq commit 349fbb35513f001a49623be8fe6704cda4ca48e2 Author: Alex Harsanyi Date: Wed May 24 14:18:39 2017 -0400 Remove cl dependency in soap-client.el and soap-inspect.el * lisp/net/soap-inspect.el: Replace cl library with cl-lib, case with cl-case, destructuring-bind with cl-destructuring-bind and loop with cl-loop. * lisp/net/soap-client.el: Replace cl library with cl-lib, defstruct with cl-defstruct, assert with cl-assert, case with cl-case, ecase with cl-ecase, loop with cl-loop and destructuring-bind with cl-destructuring-bind. Co-authored-by: Stefan Monnier diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el index 5d36cfa89b..922f698576 100644 --- a/lisp/net/soap-client.el +++ b/lisp/net/soap-client.el @@ -43,7 +43,6 @@ ;;; Code: -(eval-when-compile (require 'cl)) (require 'cl-lib) (require 'xml) @@ -298,7 +297,7 @@ be tagged with a namespace tag." ;; An element in an XML namespace, "things" stored in soap-xml-namespaces will ;; be derived from this object. -(defstruct soap-element +(cl-defstruct soap-element name ;; The "well-known" namespace tag for the element. For example, while ;; parsing XML documents, we can have different tags for the XMLSchema @@ -321,13 +320,13 @@ element name." ;; a namespace link stores an alias for an object in once namespace to a ;; "target" object possibly in a different namespace -(defstruct (soap-namespace-link (:include soap-element)) +(cl-defstruct (soap-namespace-link (:include soap-element)) target) ;; A namespace is a collection of soap-element objects under a name (the name ;; of the namespace). -(defstruct soap-namespace +(cl-defstruct soap-namespace (name nil :read-only t) ; e.g "http://xml.apache.org/xml-soap" (elements (make-hash-table :test 'equal) :read-only t)) @@ -360,9 +359,9 @@ added to the namespace." (setq name target)))))) ;; by now, name should be valid - (assert (and name (not (equal name ""))) - nil - "Cannot determine name for namespace link") + (cl-assert (and name (not (equal name ""))) + nil + "Cannot determine name for namespace link") (push (make-soap-namespace-link :name name :target target) (gethash name (soap-namespace-elements ns)))) @@ -372,7 +371,7 @@ If multiple elements with the same name exist, DISCRIMINANT-PREDICATE is used to pick one of them. This allows storing elements of different types (like a message type and a binding) but the same name." - (assert (stringp name)) + (cl-assert (stringp name)) (let ((elements (gethash name (soap-namespace-elements ns)))) (cond (discriminant-predicate (catch 'found @@ -394,14 +393,14 @@ binding) but the same name." ;; message exchange. We include here an XML schema model with a parser and ;; serializer/deserializer. -(defstruct (soap-xs-type (:include soap-element)) +(cl-defstruct (soap-xs-type (:include soap-element)) id attributes attribute-groups) ;;;;; soap-xs-basic-type -(defstruct (soap-xs-basic-type (:include soap-xs-type)) +(cl-defstruct (soap-xs-basic-type (:include soap-xs-type)) ;; Basic types are "built in" and we know how to handle them directly. ;; Other type definitions reference basic types, so we need to create them ;; in a namespace (see `soap-make-xs-basic-types') @@ -483,7 +482,7 @@ This is a specialization of `soap-encode-value' for (when (or value (eq kind 'boolean)) (let ((value-string - (case kind + (cl-case kind ((string anyURI QName ID IDREF language) (unless (stringp value) (error "Not a string value: %s" value)) @@ -495,7 +494,7 @@ This is a specialization of `soap-encode-value' for ;; string format in UTC. (format-time-string (concat - (ecase kind + (cl-ecase kind (dateTime "%Y-%m-%dT%H:%M:%S") (time "%H:%M:%S") (date "%Y-%m-%d") @@ -673,7 +672,7 @@ This is a specialization of `soap-decode-type' for (if (null contents) nil - (ecase kind + (cl-ecase kind ((string anyURI QName ID IDREF language) (car contents)) ((dateTime time date gYearMonth gYear gMonthDay gDay gMonth) (car contents)) @@ -694,7 +693,7 @@ This is a specialization of `soap-decode-type' for ;;;;; soap-xs-element -(defstruct (soap-xs-element (:include soap-element)) +(cl-defstruct (soap-xs-element (:include soap-element)) ;; NOTE: we don't support exact number of occurrences via minOccurs, ;; maxOccurs. Instead we support optional? and multiple? @@ -738,8 +737,8 @@ contains a reference, retrieve the type of the reference." (ref (xml-get-attribute-or-nil node 'ref)) (substitution-group (xml-get-attribute-or-nil node 'substitutionGroup)) (node-name (soap-l2wk (xml-node-name node)))) - (assert (memq node-name '(xsd:element xsd:group)) - "expecting xsd:element or xsd:group, got %s" node-name) + (cl-assert (memq node-name '(xsd:element xsd:group)) + "expecting xsd:element or xsd:group, got %s" node-name) (when type (setq type (soap-l2fq type 'tns))) @@ -895,11 +894,11 @@ This is a specialization of `soap-encode-value' for (soap-element-namespace-tag type))) (setf (soap-xs-element-type^ new-element) (soap-xs-complex-type-base type)) - (loop for i below (length value) - do (progn - (soap-encode-xs-element (aref value i) new-element) - ))) - (soap-encode-value value type)) + (cl-loop for i below (length value) + do (progn + (soap-encode-xs-element (aref value i) new-element) + ))) + (soap-encode-value value type)) (insert "\n")) ;; else (insert "/>\n")))) @@ -925,18 +924,18 @@ This is a specialization of `soap-decode-type' for ;;;;; soap-xs-attribute -(defstruct (soap-xs-attribute (:include soap-element)) +(cl-defstruct (soap-xs-attribute (:include soap-element)) type ; a simple type or basic type default ; the default value, if any reference) -(defstruct (soap-xs-attribute-group (:include soap-xs-type)) +(cl-defstruct (soap-xs-attribute-group (:include soap-xs-type)) reference) (defun soap-xs-parse-attribute (node) "Construct a `soap-xs-attribute' from NODE." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:attribute) - "expecting xsd:attribute, got %s" (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:attribute) + "expecting xsd:attribute, got %s" (soap-l2wk (xml-node-name node))) (let* ((name (xml-get-attribute-or-nil node 'name)) (type (soap-l2fq (xml-get-attribute-or-nil node 'type))) (default (xml-get-attribute-or-nil node 'fixed)) @@ -952,8 +951,8 @@ This is a specialization of `soap-decode-type' for (defun soap-xs-parse-attribute-group (node) "Construct a `soap-xs-attribute-group' from NODE." (let ((node-name (soap-l2wk (xml-node-name node)))) - (assert (eq node-name 'xsd:attributeGroup) - "expecting xsd:attributeGroup, got %s" node-name) + (cl-assert (eq node-name 'xsd:attributeGroup) + "expecting xsd:attributeGroup, got %s" node-name) (let ((name (xml-get-attribute-or-nil node 'name)) (id (xml-get-attribute-or-nil node 'id)) (ref (xml-get-attribute-or-nil node 'ref)) @@ -970,7 +969,7 @@ This is a specialization of `soap-decode-type' for (unless (stringp child) ;; Ignore optional annotation. ;; Ignore anyAttribute nodes. - (case (soap-l2wk (xml-node-name child)) + (cl-case (soap-l2wk (xml-node-name child)) (xsd:attribute (push (soap-xs-parse-attribute child) (soap-xs-type-attributes attribute-group))) @@ -1043,7 +1042,7 @@ See also `soap-wsdl-resolve-references'." ;;;;; soap-xs-simple-type -(defstruct (soap-xs-simple-type (:include soap-xs-type)) +(cl-defstruct (soap-xs-simple-type (:include soap-xs-type)) ;; A simple type is an extension on the basic type to which some ;; restrictions can be added. For example we can define a simple type based ;; off "string" with the restrictions that only the strings "one", "two" and @@ -1064,11 +1063,11 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-parse-simple-type (node) "Construct an `soap-xs-simple-type' object from the XML NODE." - (assert (memq (soap-l2wk (xml-node-name node)) - '(xsd:simpleType xsd:simpleContent)) - nil - "expecting xsd:simpleType or xsd:simpleContent node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (memq (soap-l2wk (xml-node-name node)) + '(xsd:simpleType xsd:simpleContent)) + nil + "expecting xsd:simpleType or xsd:simpleContent node, got %s" + (soap-l2wk (xml-node-name node))) ;; NOTE: name can be nil for inline types. Such types cannot be added to a ;; namespace. @@ -1079,7 +1078,7 @@ See also `soap-wsdl-resolve-references'." :name name :namespace-tag soap-target-xmlns :id id)) (def (soap-xml-node-find-matching-child node '(xsd:restriction xsd:extension xsd:union xsd:list)))) - (ecase (soap-l2wk (xml-node-name def)) + (cl-ecase (soap-l2wk (xml-node-name def)) (xsd:restriction (soap-xs-add-restriction def type)) (xsd:extension (soap-xs-add-extension def type)) (xsd:union (soap-xs-add-union def type)) @@ -1090,10 +1089,10 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-add-restriction (node type) "Add restrictions defined in XML NODE to TYPE, an `soap-xs-simple-type'." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:restriction) - nil - "expecting xsd:restriction node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:restriction) + nil + "expecting xsd:restriction node, got %s" + (soap-l2wk (xml-node-name node))) (setf (soap-xs-simple-type-base type) (soap-l2fq (xml-get-attribute node 'base))) @@ -1101,7 +1100,7 @@ See also `soap-wsdl-resolve-references'." (dolist (r (xml-node-children node)) (unless (stringp r) ; skip the white space (let ((value (xml-get-attribute r 'value))) - (case (soap-l2wk (xml-node-name r)) + (cl-case (soap-l2wk (xml-node-name r)) (xsd:enumeration (push value (soap-xs-simple-type-enumeration type))) (xsd:pattern @@ -1162,9 +1161,9 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-add-union (node type) "Add union members defined in XML NODE to TYPE, an `soap-xs-simple-type'." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:union) - nil - "expecting xsd:union node, got %s" (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:union) + nil + "expecting xsd:union node, got %s" (soap-l2wk (xml-node-name node))) (setf (soap-xs-simple-type-base type) (mapcar 'soap-l2fq @@ -1182,9 +1181,9 @@ See also `soap-wsdl-resolve-references'." (defun soap-xs-add-list (node type) "Add list defined in XML NODE to TYPE, a `soap-xs-simple-type'." - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:list) - nil - "expecting xsd:list node, got %s" (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:list) + nil + "expecting xsd:list node, got %s" (soap-l2wk (xml-node-name node))) ;; A simple type can be defined inline inside the list node or referenced by ;; the itemType attribute, in which case it will be resolved by the @@ -1219,7 +1218,7 @@ See also `soap-wsdl-resolve-references'." (defun soap-validate-xs-basic-type (value type) "Validate VALUE against the basic type TYPE." (let* ((kind (soap-xs-basic-type-kind type))) - (case kind + (cl-case kind ((anyType Array byte[]) value) (t @@ -1384,7 +1383,7 @@ This is a specialization of `soap-decode-type' for ;;;;; soap-xs-complex-type -(defstruct (soap-xs-complex-type (:include soap-xs-type)) +(cl-defstruct (soap-xs-complex-type (:include soap-xs-type)) indicator ; sequence, choice, all, array base elements @@ -1400,12 +1399,12 @@ This is a specialization of `soap-decode-type' for type attributes attribute-groups) - (assert (memq node-name '(xsd:complexType xsd:complexContent xsd:group)) - nil "unexpected node: %s" node-name) + (cl-assert (memq node-name '(xsd:complexType xsd:complexContent xsd:group)) + nil "unexpected node: %s" node-name) (dolist (def (xml-node-children node)) (when (consp def) ; skip text nodes - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) (xsd:attribute (push (soap-xs-parse-attribute def) attributes)) (xsd:attributeGroup (push (soap-xs-parse-attribute-group def) @@ -1416,7 +1415,7 @@ This is a specialization of `soap-decode-type' for (xsd:complexContent (dolist (def (xml-node-children def)) (when (consp def) - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) (xsd:attribute (push (soap-xs-parse-attribute def) attributes)) (xsd:attributeGroup @@ -1447,15 +1446,15 @@ This is a specialization of `soap-decode-type' for (defun soap-xs-parse-sequence (node) "Parse a sequence definition from XML NODE. Returns a `soap-xs-complex-type'" - (assert (memq (soap-l2wk (xml-node-name node)) - '(xsd:sequence xsd:choice xsd:all)) - nil - "unexpected node: %s" (soap-l2wk (xml-node-name node))) + (cl-assert (memq (soap-l2wk (xml-node-name node)) + '(xsd:sequence xsd:choice xsd:all)) + nil + "unexpected node: %s" (soap-l2wk (xml-node-name node))) (let ((type (make-soap-xs-complex-type))) (setf (soap-xs-complex-type-indicator type) - (ecase (soap-l2wk (xml-node-name node)) + (cl-ecase (soap-l2wk (xml-node-name node)) (xsd:sequence 'sequence) (xsd:all 'all) (xsd:choice 'choice))) @@ -1465,7 +1464,7 @@ Returns a `soap-xs-complex-type'" (dolist (r (xml-node-children node)) (unless (stringp r) ; skip the white space - (case (soap-l2wk (xml-node-name r)) + (cl-case (soap-l2wk (xml-node-name r)) ((xsd:element xsd:group) (push (soap-xs-parse-element r) (soap-xs-complex-type-elements type))) @@ -1489,10 +1488,10 @@ Returns a `soap-xs-complex-type'" (defun soap-xs-parse-extension-or-restriction (node) "Parse an extension or restriction definition from XML NODE. Return a `soap-xs-complex-type'." - (assert (memq (soap-l2wk (xml-node-name node)) - '(xsd:extension xsd:restriction)) - nil - "unexpected node: %s" (soap-l2wk (xml-node-name node))) + (cl-assert (memq (soap-l2wk (xml-node-name node)) + '(xsd:extension xsd:restriction)) + nil + "unexpected node: %s" (soap-l2wk (xml-node-name node))) (let (type attributes attribute-groups @@ -1507,7 +1506,7 @@ Return a `soap-xs-complex-type'." (dolist (def (xml-node-children node)) (when (consp def) ; skip text nodes - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) ((xsd:sequence xsd:choice xsd:all) (setq type (soap-xs-parse-sequence def))) (xsd:attribute @@ -1628,7 +1627,7 @@ position. This is a specialization of `soap-encode-value' for `soap-xs-complex-type' objects." - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) (array (error "Arrays of type soap-encode-xs-complex-type are handled elsewhere")) ((sequence choice all nil) @@ -1650,7 +1649,7 @@ This is a specialization of `soap-encode-value' for (let ((e-name (intern e-name))) (dolist (v value) (when (equal (car v) e-name) - (incf instance-count) + (cl-incf instance-count) (soap-encode-value (cdr v) candidate)))) (if (soap-xs-complex-type-indicator type) (let ((current-point (point))) @@ -1658,12 +1657,12 @@ This is a specialization of `soap-encode-value' for ;; characters were inserted in the buffer. (soap-encode-value value candidate) (when (not (equal current-point (point))) - (incf instance-count))) + (cl-incf instance-count))) (dolist (v value) (let ((current-point (point))) (soap-encode-value v candidate) (when (not (equal current-point (point))) - (incf instance-count)))))))) + (cl-incf instance-count)))))))) ;; Do some sanity checking (let* ((indicator (soap-xs-complex-type-indicator type)) (element-type (soap-xs-element-type element)) @@ -1801,7 +1800,7 @@ type-info stored in TYPE. This is a specialization of `soap-decode-type' for `soap-xs-basic-type' objects." - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) (array (let ((result nil) (element-type (soap-xs-complex-type-base type))) @@ -1878,7 +1877,7 @@ This is a specialization of `soap-decode-type' for (list node))) (element-type (soap-xs-element-type element))) (dolist (node children) - (incf instance-count) + (cl-incf instance-count) (let* ((attributes (soap-decode-xs-attributes element-type node)) ;; Attributes may specify xsi:type override. @@ -1939,11 +1938,11 @@ This is a specialization of `soap-decode-type' for ;;;;; WSDL document elements -(defstruct (soap-message (:include soap-element)) +(cl-defstruct (soap-message (:include soap-element)) parts ; ALIST of NAME => WSDL-TYPE name ) -(defstruct (soap-operation (:include soap-element)) +(cl-defstruct (soap-operation (:include soap-element)) parameter-order input ; (NAME . MESSAGE) output ; (NAME . MESSAGE) @@ -1951,13 +1950,13 @@ This is a specialization of `soap-decode-type' for input-action ; WS-addressing action string output-action) ; WS-addressing action string -(defstruct (soap-port-type (:include soap-element)) +(cl-defstruct (soap-port-type (:include soap-element)) operations) ; a namespace of operations ;; A bound operation is an operation which has a soap action and a use ;; method attached -- these are attached as part of a binding and we ;; can have different bindings for the same operations. -(defstruct soap-bound-operation +(cl-defstruct soap-bound-operation operation ; SOAP-OPERATION soap-action ; value for SOAPAction HTTP header soap-headers ; list of (message part use) @@ -1966,11 +1965,11 @@ This is a specialization of `soap-decode-type' for ; http://www.w3.org/TR/wsdl#_soap:body ) -(defstruct (soap-binding (:include soap-element)) +(cl-defstruct (soap-binding (:include soap-element)) port-type (operations (make-hash-table :test 'equal) :readonly t)) -(defstruct (soap-port (:include soap-element)) +(cl-defstruct (soap-port (:include soap-element)) service-url binding) @@ -1978,10 +1977,10 @@ This is a specialization of `soap-decode-type' for ;;;;; The WSDL document ;; The WSDL data structure used for encoding/decoding SOAP messages -(defstruct (soap-wsdl - ;; NOTE: don't call this constructor, see `soap-make-wsdl' - (:constructor soap-make-wsdl^) - (:copier soap-copy-wsdl)) +(cl-defstruct (soap-wsdl + ;; NOTE: don't call this constructor, see `soap-make-wsdl' + (:constructor soap-make-wsdl^) + (:copier soap-copy-wsdl)) origin ; file or URL from which this wsdl was loaded current-file ; most-recently fetched file or URL xmlschema-imports ; a list of schema imports @@ -2107,16 +2106,16 @@ used to resolve the namespace alias." "Parse a schema NODE, placing the results in WSDL. Return a SOAP-NAMESPACE containing the elements." (soap-with-local-xmlns node - (assert (eq (soap-l2wk (xml-node-name node)) 'xsd:schema) - nil - "expecting an xsd:schema node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'xsd:schema) + nil + "expecting an xsd:schema node, got %s" + (soap-l2wk (xml-node-name node))) (let ((ns (make-soap-namespace :name (soap-get-target-namespace node)))) (dolist (def (xml-node-children node)) (unless (stringp def) ; skip text nodes - (case (soap-l2wk (xml-node-name def)) + (cl-case (soap-l2wk (xml-node-name def)) (xsd:import ;; Imports will be processed later ;; NOTE: we should expand the location now! @@ -2195,7 +2194,7 @@ See also `soap-resolve-references' and (message (cdr input))) ;; Name this part if it was not named (when (or (null name) (equal name "")) - (setq name (format "in%d" (incf counter)))) + (setq name (format "in%d" (cl-incf counter)))) (when (soap-name-p message) (setf (soap-operation-input operation) (cons (intern name) @@ -2206,7 +2205,7 @@ See also `soap-resolve-references' and (let ((name (car output)) (message (cdr output))) (when (or (null name) (equal name "")) - (setq name (format "out%d" (incf counter)))) + (setq name (format "out%d" (cl-incf counter)))) (when (soap-name-p message) (setf (soap-operation-output operation) (cons (intern name) @@ -2218,7 +2217,7 @@ See also `soap-resolve-references' and (let ((name (car fault)) (message (cdr fault))) (when (or (null name) (equal name "")) - (setq name (format "fault%d" (incf counter)))) + (setq name (format "fault%d" (cl-incf counter)))) (if (soap-name-p message) (push (cons (intern name) (soap-wsdl-get message wsdl 'soap-message-p)) @@ -2304,19 +2303,19 @@ traverse an element tree." ;; If this namespace does not have an alias, create one for it. (catch 'done (while t - (setq nstag (format "ns%d" (incf nstag-id))) + (setq nstag (format "ns%d" (cl-incf nstag-id))) (unless (assoc nstag alias-table) (soap-wsdl-add-alias nstag (soap-namespace-name ns) wsdl) (throw 'done t))))) (maphash (lambda (_name element) (cond ((soap-element-p element) ; skip links - (incf nprocessed) + (cl-incf nprocessed) (soap-resolve-references element wsdl)) ((listp element) (dolist (e element) (when (soap-element-p e) - (incf nprocessed) + (cl-incf nprocessed) (soap-resolve-references e wsdl)))))) (soap-namespace-elements ns))))) wsdl) @@ -2391,9 +2390,9 @@ Build on WSDL if it is provided." "Assert that NODE is valid." (soap-with-local-xmlns node (let ((node-name (soap-l2wk (xml-node-name node)))) - (assert (eq node-name 'wsdl:definitions) - nil - "expecting wsdl:definitions node, got %s" node-name)))) + (cl-assert (eq node-name 'wsdl:definitions) + nil + "expecting wsdl:definitions node, got %s" node-name)))) (defun soap-parse-wsdl-phase-fetch-imports (node wsdl) "Fetch and load files imported by NODE into WSDL." @@ -2473,10 +2472,10 @@ Build on WSDL if it is provided." (defun soap-parse-message (node) "Parse NODE as a wsdl:message and return the corresponding type." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:message) - nil - "expecting wsdl:message node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:message) + nil + "expecting wsdl:message node, got %s" + (soap-l2wk (xml-node-name node))) (let ((name (xml-get-attribute-or-nil node 'name)) parts) (dolist (p (soap-xml-get-children1 node 'wsdl:part)) @@ -2500,10 +2499,10 @@ Build on WSDL if it is provided." (defun soap-parse-port-type (node) "Parse NODE as a wsdl:portType and return the corresponding port." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:portType) - nil - "expecting wsdl:portType node got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:portType) + nil + "expecting wsdl:portType node got %s" + (soap-l2wk (xml-node-name node))) (let* ((soap-target-xmlns (concat "urn:" (xml-get-attribute node 'name))) (ns (make-soap-namespace :name soap-target-xmlns))) (dolist (node (soap-xml-get-children1 node 'wsdl:operation)) @@ -2522,14 +2521,14 @@ Build on WSDL if it is provided." ;; link all messages from this namespace, as this namespace ;; will be used for decoding the response. - (destructuring-bind (name . message) (soap-operation-input o) + (cl-destructuring-bind (name . message) (soap-operation-input o) (soap-namespace-put-link name message ns)) - (destructuring-bind (name . message) (soap-operation-output o) + (cl-destructuring-bind (name . message) (soap-operation-output o) (soap-namespace-put-link name message ns)) (dolist (fault (soap-operation-faults o)) - (destructuring-bind (name . message) fault + (cl-destructuring-bind (name . message) fault (soap-namespace-put-link name message ns))) ))))) @@ -2539,10 +2538,10 @@ Build on WSDL if it is provided." (defun soap-parse-operation (node) "Parse NODE as a wsdl:operation and return the corresponding type." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:operation) - nil - "expecting wsdl:operation node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:operation) + nil + "expecting wsdl:operation node, got %s" + (soap-l2wk (xml-node-name node))) (let ((name (xml-get-attribute node 'name)) (parameter-order (split-string (xml-get-attribute node 'parameterOrder))) @@ -2579,10 +2578,10 @@ Build on WSDL if it is provided." (defun soap-parse-binding (node) "Parse NODE as a wsdl:binding and return the corresponding type." - (assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:binding) - nil - "expecting wsdl:binding node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'wsdl:binding) + nil + "expecting wsdl:binding node, got %s" + (soap-l2wk (xml-node-name node))) (let ((name (xml-get-attribute node 'name)) (type (xml-get-attribute node 'type))) (let ((binding (make-soap-binding :name name @@ -2693,8 +2692,8 @@ decode function to perform the actual decoding." (when result (throw 'done result)))))) (t (let ((decoder (get (aref type 0) 'soap-decoder))) - (assert decoder nil - "no soap-decoder for %s type" (aref type 0)) + (cl-assert decoder nil + "no soap-decoder for %s type" (aref type 0)) (funcall decoder type node)))))))))) (defun soap-decode-any-type (node) @@ -2769,10 +2768,10 @@ decode function to perform the actual decoding." OPERATION is the WSDL operation for which we expect the response, WSDL is used to decode the NODE" (soap-with-local-xmlns node - (assert (eq (soap-l2wk (xml-node-name node)) 'soap:Envelope) - nil - "expecting soap:Envelope node, got %s" - (soap-l2wk (xml-node-name node))) + (cl-assert (eq (soap-l2wk (xml-node-name node)) 'soap:Envelope) + nil + "expecting soap:Envelope node, got %s" + (soap-l2wk (xml-node-name node))) (let ((headers (soap-xml-get-children1 node 'soap:Header)) (body (car (soap-xml-get-children1 node 'soap:Body)))) @@ -2879,8 +2878,8 @@ for the type and calls that specialized function to do the work. Attributes are inserted in the current buffer at the current position." (let ((attribute-encoder (get (aref type 0) 'soap-attribute-encoder))) - (assert attribute-encoder nil - "no soap-attribute-encoder for %s type" (aref type 0)) + (cl-assert attribute-encoder nil + "no soap-attribute-encoder for %s type" (aref type 0)) (funcall attribute-encoder value type))) (defun soap-encode-value (value type) @@ -2893,7 +2892,7 @@ is to be encoded. This is a generic function which finds an encoder function based on TYPE and calls that encoder to do the work." (let ((encoder (get (aref type 0) 'soap-encoder))) - (assert encoder nil "no soap-encoder for %s type" (aref type 0)) + (cl-assert encoder nil "no soap-encoder for %s type" (aref type 0)) (funcall encoder value type)) (when (soap-element-namespace-tag type) (add-to-list 'soap-encoded-namespaces (soap-element-namespace-tag type)))) @@ -2909,9 +2908,9 @@ being used." (use (soap-bound-operation-use operation)) (message (cdr (soap-operation-input op))) (parameter-order (soap-operation-parameter-order op)) - (param-table (loop for formal in parameter-order - for value in parameters - collect (cons formal value)))) + (param-table (cl-loop for formal in parameter-order + for value in parameters + collect (cons formal value)))) (unless (= (length parameter-order) (length parameters)) (error "Wrong number of parameters for %s: expected %d, got %s" @@ -3059,41 +3058,41 @@ OPERATION-NAME and PARAMETERS are as described in `soap-invoke'." (lambda (status) (let ((data-buffer (current-buffer))) (unwind-protect - (let ((error-status (plist-get status :error))) - (if error-status - (signal (car error-status) (cdr error-status)) - (apply callback - (soap-parse-envelope - (soap-parse-server-response) - operation wsdl) - cbargs))) + (let ((error-status (plist-get status :error))) + (if error-status + (signal (car error-status) (cdr error-status)) + (apply callback + (soap-parse-envelope + (soap-parse-server-response) + operation wsdl) + cbargs))) ;; Ensure the url-retrieve buffer is not leaked. (and (buffer-live-p data-buffer) (kill-buffer data-buffer)))))) - (let ((buffer (url-retrieve-synchronously - (soap-port-service-url port)))) - (condition-case err - (with-current-buffer buffer - (declare (special url-http-response-status)) - (if (null url-http-response-status) - (error "No HTTP response from server")) - (if (and soap-debug (> url-http-response-status 299)) - ;; This is a warning because some SOAP errors come - ;; back with a HTTP response 500 (internal server - ;; error) - (warn "Error in SOAP response: HTTP code %s" - url-http-response-status)) - (soap-parse-envelope (soap-parse-server-response) - operation wsdl)) - (soap-error - ;; Propagate soap-errors -- they are error replies of the - ;; SOAP protocol and don't indicate a communication - ;; problem or a bug in this code. - (signal (car err) (cdr err))) - (error - (when soap-debug - (pop-to-buffer buffer)) - (error (error-message-string err))))))))) + (let ((buffer (url-retrieve-synchronously + (soap-port-service-url port)))) + (condition-case err + (with-current-buffer buffer + (declare (special url-http-response-status)) + (if (null url-http-response-status) + (error "No HTTP response from server")) + (if (and soap-debug (> url-http-response-status 299)) + ;; This is a warning because some SOAP errors come + ;; back with a HTTP response 500 (internal server + ;; error) + (warn "Error in SOAP response: HTTP code %s" + url-http-response-status)) + (soap-parse-envelope (soap-parse-server-response) + operation wsdl)) + (soap-error + ;; Propagate soap-errors -- they are error replies of the + ;; SOAP protocol and don't indicate a communication + ;; problem or a bug in this code. + (signal (car err) (cdr err))) + (error + (when soap-debug + (pop-to-buffer buffer)) + (error (error-message-string err))))))))) (defun soap-invoke (wsdl service operation-name &rest parameters) "Invoke a SOAP operation and return the result. diff --git a/lisp/net/soap-inspect.el b/lisp/net/soap-inspect.el index db83cf8463..cd14eddb4f 100644 --- a/lisp/net/soap-inspect.el +++ b/lisp/net/soap-inspect.el @@ -37,8 +37,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) - +(require 'cl-lib) (require 'soap-client) ;;; sample-value @@ -53,13 +52,13 @@ will be called." (let ((sample-value (get (aref type 0) 'soap-sample-value))) (if sample-value (funcall sample-value type) - (error "Cannot provide sample value for type %s" (aref type 0))))) + (error "Cannot provide sample value for type %s" (aref type 0))))) (defun soap-sample-value-for-xs-basic-type (type) "Provide a sample value for TYPE, an xs-basic-type. This is a specialization of `soap-sample-value' for xs-basic-type objects." - (case (soap-xs-basic-type-kind type) + (cl-case (soap-xs-basic-type-kind type) (string "a string") (anyURI "an URI") (QName "a QName") @@ -77,7 +76,7 @@ objects." (if (soap-xs-element-name element) (cons (intern (soap-xs-element-name element)) (soap-sample-value (soap-xs-element-type element))) - (soap-sample-value (soap-xs-element-type element)))) + (soap-sample-value (soap-xs-element-type element)))) (defun soap-sample-value-for-xs-attribute (attribute) "Provide a sample value for ATTRIBUTE, a WSDL attribute. @@ -119,20 +118,20 @@ This is a specialization of `soap-sample-value' for ((soap-xs-simple-type-pattern type) (format "a string matching %s" (soap-xs-simple-type-pattern type))) ((soap-xs-simple-type-length-range type) - (destructuring-bind (low . high) (soap-xs-simple-type-length-range type) + (cl-destructuring-bind (low . high) (soap-xs-simple-type-length-range type) (cond - ((and low high) - (format "a string between %d and %d chars long" low high)) - (low (format "a string at least %d chars long" low)) - (high (format "a string at most %d chars long" high)) - (t (format "a string OOPS"))))) + ((and low high) + (format "a string between %d and %d chars long" low high)) + (low (format "a string at least %d chars long" low)) + (high (format "a string at most %d chars long" high)) + (t (format "a string OOPS"))))) ((soap-xs-simple-type-integer-range type) - (destructuring-bind (min . max) (soap-xs-simple-type-integer-range type) + (cl-destructuring-bind (min . max) (soap-xs-simple-type-integer-range type) (cond - ((and min max) (+ min (random (- max min)))) - (min (+ min (random 10))) - (max (random max)) - (t (random 100))))) + ((and min max) (+ min (random (- max min)))) + (min (+ min (random 10))) + (max (random max)) + (t (random 100))))) ((consp (soap-xs-simple-type-base type)) ; an union of values (let ((base (soap-xs-simple-type-base type))) (soap-sample-value (nth (random (length base)) base)))) @@ -146,7 +145,7 @@ This is a specialization of `soap-sample-value' for (append (mapcar 'soap-sample-value-for-xs-attribute (soap-xs-type-attributes type)) - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) (array (let* ((element-type (soap-xs-complex-type-base type)) (sample1 (soap-sample-value element-type)) @@ -251,24 +250,24 @@ entire WSDL can be inspected." (define-button-type 'soap-client-describe-link - 'face 'link - 'help-echo "mouse-2, RET: describe item" - 'follow-link t - 'action (lambda (button) - (let ((item (button-get button 'item))) - (soap-inspect item))) - 'skip t) + 'face 'link + 'help-echo "mouse-2, RET: describe item" + 'follow-link t + 'action (lambda (button) + (let ((item (button-get button 'item))) + (soap-inspect item))) + 'skip t) (define-button-type 'soap-client-describe-back-link - 'face 'link - 'help-echo "mouse-2, RET: browse the previous item" - 'follow-link t - 'action (lambda (_button) - (let ((item (pop soap-inspect-previous-items))) - (when item - (setq soap-inspect-current-item nil) - (soap-inspect item)))) - 'skip t) + 'face 'link + 'help-echo "mouse-2, RET: browse the previous item" + 'follow-link t + 'action (lambda (_button) + (let ((item (pop soap-inspect-previous-items))) + (when item + (setq soap-inspect-current-item nil) + (soap-inspect item)))) + 'skip t) (defun soap-insert-describe-button (element) "Insert a button to inspect ELEMENT when pressed." @@ -323,7 +322,7 @@ soap-xs-attribute-group, in the current buffer." (insert ", ") (setq first-time nil)) (soap-insert-describe-button b))) - (soap-insert-describe-button (soap-xs-simple-type-base type))) + (soap-insert-describe-button (soap-xs-simple-type-base type))) (insert "\nAttributes: ") (dolist (attribute (soap-xs-simple-type-attributes type)) (let ((name (or (soap-xs-attribute-name attribute) "*inline*")) @@ -359,7 +358,7 @@ soap-xs-attribute-group, in the current buffer." TYPE is a `soap-xs-complex-type'" (insert "Complex type: " (soap-element-fq-name type)) (insert "\nKind: ") - (case (soap-xs-complex-type-indicator type) + (cl-case (soap-xs-complex-type-indicator type) ((sequence all) (insert "a sequence ") (when (soap-xs-complex-type-base type) @@ -394,10 +393,10 @@ TYPE is a `soap-xs-complex-type'" (insert (make-string (- type-width (length (soap-element-fq-name type))) ?\ )) - (when (soap-xs-element-multiple? element) - (insert " multiple")) - (when (soap-xs-element-optional? element) - (insert " optional")))))) + (when (soap-xs-element-multiple? element) + (insert " multiple")) + (when (soap-xs-element-optional? element) + (insert " optional")))))) (choice (insert "a choice ") (when (soap-xs-complex-type-base type) @@ -449,11 +448,11 @@ TYPE is a `soap-xs-complex-type'" "Insert information about PORT-TYPE into the current buffer." (insert "Port-type name: " (soap-element-fq-name port-type) "\n") (insert "Operations:\n") - (loop for o being the hash-values of - (soap-namespace-elements (soap-port-type-operations port-type)) - do (progn - (insert "\t") - (soap-insert-describe-button (car o))))) + (cl-loop for o being the hash-values of + (soap-namespace-elements (soap-port-type-operations port-type)) + do (progn + (insert "\t") + (soap-insert-describe-button (car o))))) (defun soap-inspect-binding (binding) "Insert information about BINDING into the current buffer." @@ -461,13 +460,13 @@ TYPE is a `soap-xs-complex-type'" (insert "\n") (insert "Bound operations:\n") (let* ((ophash (soap-binding-operations binding)) - (operations (loop for o being the hash-keys of ophash - collect o)) + (operations (cl-loop for o being the hash-keys of ophash + collect o)) op-name-width) (setq operations (sort operations 'string<)) - (setq op-name-width (loop for o in operations maximizing (length o))) + (setq op-name-width (cl-loop for o in operations maximizing (length o))) (dolist (op operations) (let* ((bound-op (gethash op ophash)) commit 1a9ce7c54e99d80fb515a33edbeeb75fd3239526 Author: Michael Albinus Date: Thu May 25 10:04:12 2017 +0200 Switch Tramp to cl-lib * lisp/net/tramp-compat.el (cl-lib): Require it rather than cl. * lisp/net/tramp-ftp.el: Don't require cl. * lisp/net/tramp-gvfs.el: Don't require cl. (tramp-gvfs-handler-mounted-unmounted) (tramp-gvfs-connection-mounted-p): Use `cl-*' macros. * lisp/net/tramp-sh.el: Don't require cl. (tramp-set-file-uid-gid): Use `shell-quote-argument'. (tramp-sh-gvfs-monitor-dir-process-filter) (tramp-sh-inotifywait-process-filter): Use `cl-*' macros. * lisp/net/tramp-smb.el: Don't require cl. (tramp-smb-read-file-entry): Use `cl-*' macros. * lisp/net/tramp.el (cl-lib): Require it rather than cl. (tramp-parse-file, tramp-parse-shostkeys-sknownhosts) (tramp-parse-passwd, tramp-parse-etc-group) (tramp-parse-putty): Use `cl-*' macros. diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index 53266e806c..392a28c59d 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -29,12 +29,9 @@ ;;; Code: -;; Pacify byte-compiler. -(eval-when-compile - (require 'cl)) - (require 'auth-source) (require 'advice) +(require 'cl-lib) (require 'custom) (require 'format-spec) (require 'parse-time) diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index 44a4ccadac..8e489eee80 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el @@ -32,7 +32,6 @@ ;; Pacify byte-compiler. (eval-when-compile - (require 'cl) (require 'custom)) (defvar ange-ftp-ftp-name-arg) (defvar ange-ftp-ftp-name-res) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index ad9bd819c0..57a135139a 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -106,7 +106,6 @@ ;; Pacify byte-compiler. (eval-when-compile - (require 'cl) (require 'custom)) ;;;###tramp-autoload @@ -1386,9 +1385,9 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." ;; elements. (while (stringp (car elt)) (setq elt (cdr elt))) (let* ((fuse-mountpoint (tramp-gvfs-dbus-byte-array-to-string (cadr elt))) - (mount-spec (caddr elt)) + (mount-spec (cl-caddr elt)) (default-location (tramp-gvfs-dbus-byte-array-to-string - (cadddr elt))) + (cl-cadddr elt))) (method (tramp-gvfs-dbus-byte-array-to-string (cadr (assoc "type" (cadr mount-spec))))) (user (tramp-gvfs-dbus-byte-array-to-string @@ -1472,9 +1471,9 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." (while (stringp (car elt)) (setq elt (cdr elt))) (let* ((fuse-mountpoint (tramp-gvfs-dbus-byte-array-to-string (cadr elt))) - (mount-spec (caddr elt)) + (mount-spec (cl-caddr elt)) (default-location (tramp-gvfs-dbus-byte-array-to-string - (cadddr elt))) + (cl-cadddr elt))) (method (tramp-gvfs-dbus-byte-array-to-string (cadr (assoc "type" (cadr mount-spec))))) (user (tramp-gvfs-dbus-byte-array-to-string diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 4b89c17347..84782a4c7f 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -31,7 +31,6 @@ ;; Pacify byte-compiler. (eval-when-compile - (require 'cl) (require 'dired)) (declare-function dired-remove-file "dired-aux") @@ -1557,7 +1556,7 @@ be non-negative integers." (gid (or (and (natnump gid) gid) (tramp-get-local-gid 'integer)))) (tramp-call-process nil "chown" nil nil nil - (format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))))) + (format "%d:%d" uid gid) (shell-quote-argument filename))))))) (defun tramp-remote-selinux-p (vec) "Check, whether SELINUX is enabled on the remote host." @@ -3674,13 +3673,13 @@ file-notify events." (when file1 (concat remote-prefix file1))))) (setq string (replace-match "" nil nil string)) ;; Remove watch when file or directory to be watched is deleted. - (when (and (member (caadr object) '(moved deleted)) + (when (and (member (cl-caadr object) '(moved deleted)) (string-equal file (process-get proc 'watch-name))) (delete-process proc)) ;; Usually, we would add an Emacs event now. Unfortunately, ;; `unread-command-events' does not accept several events at ;; once. Therefore, we apply the handler directly. - (when (member (caadr object) events) + (when (member (cl-caadr object) events) (tramp-compat-funcall 'file-notify-handle-event `(file-notify ,object file-notify-callback))))) @@ -3714,12 +3713,12 @@ file-notify events." (split-string (match-string 1 line) "," 'omit)) (match-string 3 line)))) ;; Remove watch when file or directory to be watched is deleted. - (when (member (caadr object) '(move-self delete-self ignored)) + (when (member (cl-caadr object) '(move-self delete-self ignored)) (delete-process proc)) ;; Usually, we would add an Emacs event now. Unfortunately, ;; `unread-command-events' does not accept several events at ;; once. Therefore, we apply the handler directly. - (when (member (caadr object) events) + (when (member (cl-caadr object) events) (tramp-compat-funcall 'file-notify-handle-event `(file-notify ,object file-notify-callback))))))) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 7b2a1ba874..88db8eaf0e 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -29,10 +29,6 @@ (require 'tramp) -;; Pacify byte-compiler. -(eval-when-compile - (require 'cl)) - ;; Define SMB method ... ;;;###tramp-autoload (defconst tramp-smb-method "smb" @@ -1655,13 +1651,13 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." size 0)) ;; Real listing. - (block nil + (cl-block nil ;; year. (if (string-match "\\([0-9]+\\)$" line) (setq year (string-to-number (match-string 1 line)) line (substring line 0 -5)) - (return)) + (cl-return)) ;; time. (if (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)$" line) @@ -1669,24 +1665,24 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." min (string-to-number (match-string 2 line)) sec (string-to-number (match-string 3 line)) line (substring line 0 -9)) - (return)) + (cl-return)) ;; day. (if (string-match "\\([0-9]+\\)$" line) (setq day (string-to-number (match-string 1 line)) line (substring line 0 -3)) - (return)) + (cl-return)) ;; month. (if (string-match "\\(\\w+\\)$" line) (setq month (match-string 1 line) line (substring line 0 -4)) - (return)) + (cl-return)) ;; weekday. (if (string-match "\\(\\w+\\)$" line) (setq line (substring line 0 -5)) - (return)) + (cl-return)) ;; size. (if (string-match "\\([0-9]+\\)$" line) @@ -1695,7 +1691,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." (when (string-match "\\([ADHRSV]+\\)" (substring line length)) (setq length (+ length (match-end 0)))) (setq line (substring line 0 length))) - (return)) + (cl-return)) ;; mode: ARCH, DIR, HIDDEN, RONLY, SYSTEM, VOLID. (if (string-match "\\([ADHRSV]+\\)?$" line) @@ -1708,12 +1704,12 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." (lambda (_x) "") " " (concat "r" (if (string-match "R" mode) "-" "w") "x")))) line (substring line 0 -6)) - (return)) + (cl-return)) ;; localname. (if (string-match "^\\s-+\\(\\S-\\(.*\\S-\\)?\\)\\s-*$" line) (setq localname (match-string 1 line)) - (return)))) + (cl-return)))) (when (and localname mode size) (setq mtime diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index b97a7a877c..a1cd90bec7 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -58,8 +58,7 @@ (require 'tramp-compat) ;; Pacify byte-compiler. -(eval-when-compile - (require 'cl)) +(require 'cl-lib) (defvar auto-save-file-name-transforms) (defvar eshell-path-env) (defvar ls-lisp-use-insert-directory-program) @@ -1134,8 +1133,8 @@ calling HANDLER.") ;; internal data structure. Convenience functions for internal ;; data structure. -;; The basic structure for remote file names. We use a list, -;; otherwise the test in `tramp-cache-data' fails. +;; The basic structure for remote file names. We use a list :type, +;; otherwise the persistent data are not read in tramp-cache.el. (cl-defstruct (tramp-file-name (:type list) :named) method user domain host port localname hop) @@ -2588,7 +2587,7 @@ User is always nil." (with-temp-buffer (insert-file-contents filename) (goto-char (point-min)) - (loop while (not (eobp)) collect (funcall function)))))) + (cl-loop while (not (eobp)) collect (funcall function)))))) ;;;###tramp-autoload (defun tramp-parse-rhosts (filename) @@ -2640,9 +2639,10 @@ User is always nil." ;; `default-directory' is remote. (let* ((default-directory (tramp-compat-temporary-file-directory)) (files (and (file-directory-p dirname) (directory-files dirname)))) - (loop for f in files - when (and (not (string-match "^\\.\\.?$" f)) (string-match regexp f)) - collect (list nil (match-string 1 f))))) + (cl-loop + for f in files + when (and (not (string-match "^\\.\\.?$" f)) (string-match regexp f)) + collect (list nil (match-string 1 f))))) ;;;###tramp-autoload (defun tramp-parse-shostkeys (dirname) @@ -2680,8 +2680,8 @@ Host is always \"localhost\"." (with-temp-buffer (when (zerop (tramp-call-process nil "getent" nil t nil "passwd")) (goto-char (point-min)) - (loop while (not (eobp)) collect - (tramp-parse-etc-group-group)))) + (cl-loop while (not (eobp)) collect + (tramp-parse-etc-group-group)))) (tramp-parse-file filename 'tramp-parse-passwd-group)))) (defun tramp-parse-passwd-group () @@ -2703,8 +2703,8 @@ Host is always \"localhost\"." (with-temp-buffer (when (zerop (tramp-call-process nil "getent" nil t nil "group")) (goto-char (point-min)) - (loop while (not (eobp)) collect - (tramp-parse-etc-group-group)))) + (cl-loop while (not (eobp)) collect + (tramp-parse-etc-group-group)))) (tramp-parse-file filename 'tramp-parse-etc-group-group)))) (defun tramp-parse-etc-group-group () @@ -2746,8 +2746,8 @@ User is always nil." (when (zerop (tramp-call-process nil "reg" nil t nil "query" registry-or-dirname)) (goto-char (point-min)) - (loop while (not (eobp)) collect - (tramp-parse-putty-group registry-or-dirname))))) + (cl-loop while (not (eobp)) collect + (tramp-parse-putty-group registry-or-dirname))))) ;; UNIX case. (tramp-parse-shostkeys-sknownhosts registry-or-dirname (concat "^\\(" tramp-host-regexp "\\)$")))) commit bfdc27c5f60765a57164e9b12f34856ae90b5888 Author: Paul Eggert Date: Thu May 25 00:43:13 2017 -0700 * CONTRIBUTE: Suggest autogen.sh's 'all' operand. diff --git a/CONTRIBUTE b/CONTRIBUTE index 188ec86470..5fd197305b 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -14,7 +14,7 @@ Briefly, the following shell commands build and run Emacs from scratch: git config --global transfer.fsckObjects true git clone git://git.sv.gnu.org/emacs.git cd emacs - ./autogen.sh + ./autogen.sh all ./configure make src/emacs commit d7284da858b38db4737f7e1f587c63390bee4328 Author: Paul Eggert Date: Thu May 25 00:24:51 2017 -0700 Port ATTRIBUTE_MAY_ALIAS to recent icc * src/conf_post.h (ATTRIBUTE_MAY_ALIAS) [__ICC]: Define to empty. Otherwise, icc (ICC) 17.0.4 20170411 says “warning #2621: attribute "__may_alias__" does not apply here” for constructs like ‘struct sockaddr *sa = (whatever); struct sockaddr_in __attribute__ ((__may_alias__)) *sin = (struct sockaddr_in *) sa;’. diff --git a/src/conf_post.h b/src/conf_post.h index c05c93b819..5e1d8457de 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -263,7 +263,7 @@ extern int emacs_setenv_TZ (char const *); #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST #define ATTRIBUTE_UNUSED _GL_UNUSED -#if GNUC_PREREQ (3, 3, 0) +#if GNUC_PREREQ (3, 3, 0) && !defined __ICC # define ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) #else # define ATTRIBUTE_MAY_ALIAS commit 9ebc2bbe3c1efea79810261533791bdf48a63760 Author: Paul Eggert Date: Thu May 25 00:13:14 2017 -0700 Merge from gnulib This incorporates: 2017-05-25 port to recent icc * lib/intprops.h: Copy from gnulib. diff --git a/lib/intprops.h b/lib/intprops.h index 8f5ad54515..28f43613fe 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -219,7 +219,11 @@ : (max) >> (b) < (a)) /* True if __builtin_add_overflow (A, B, P) works when P is non-null. */ -#define _GL_HAS_BUILTIN_OVERFLOW (5 <= __GNUC__) +#if 5 <= __GNUC__ && !defined __ICC +# define _GL_HAS_BUILTIN_OVERFLOW 1 +#else +# define _GL_HAS_BUILTIN_OVERFLOW 0 +#endif /* True if __builtin_add_overflow_p (A, B, C) works. */ #define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) commit b2ec91db89739153b39d10c15701b57aae7e251c Author: Michael Albinus Date: Wed May 24 22:26:20 2017 +0200 Fix Tramp for python.el * lisp/net/tramp.el (tramp-get-connection-process): Check, that VEC is a `tramp-file-name' structure. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index c481ec66ce..b97a7a877c 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1394,7 +1394,7 @@ from the default one." "Get the connection process to be used for VEC. In case a second asynchronous communication has been started, it is different from the default one." - (get-process (tramp-get-connection-name vec))) + (and (tramp-file-name-p vec) (get-process (tramp-get-connection-name vec)))) (defun tramp-set-connection-local-variables (vec) "Set connection-local variables in the connection buffer used for VEC. commit ad8b60ee7423116574ebd2a0059012a303938fd3 Author: Alan Third Date: Wed May 24 20:18:52 2017 +0100 Raise version of macOS we define instancetype for (bug#27059) * src/nsterm.m: Increase supported version number. diff --git a/src/nsterm.h b/src/nsterm.h index d98f0d03d3..8f3d92b353 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -66,7 +66,7 @@ typedef float EmacsCGFloat; Clang don't support it, and I don't know if GCC supports it at all. Should this be tested for in ./configure? */ #if defined (NS_IMPL_GNUSTEP) - || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10 typedef id instancetype; typedef NSUInteger NSWindowStyleMask; #endif commit d61d443fc0559314a2c22b1c120091de88585935 Author: Alan Third Date: Wed May 24 19:40:19 2017 +0100 Define new types on macOS 10.6 (bug#27041) * src/nsterm.h: Enable instancetype typedef for older macOS, and use correct NSUInteger instead of int. diff --git a/src/nsterm.h b/src/nsterm.h index 443a40ed6f..d98f0d03d3 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -62,11 +62,13 @@ typedef CGFloat EmacsCGFloat; typedef float EmacsCGFloat; #endif -/* FIXME: It looks as though instancetype will be supported in GNUstep - at some point, but I'm not sure what version. */ -#ifdef NS_IMPL_GNUSTEP +/* FIXME: instancetype is a language built-in, but older versions of + Clang don't support it, and I don't know if GCC supports it at all. + Should this be tested for in ./configure? */ +#if defined (NS_IMPL_GNUSTEP) + || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 typedef id instancetype; -typedef int NSWindowStyleMask; +typedef NSUInteger NSWindowStyleMask; #endif /* ========================================================================== commit c0f90833a716a4d577dbd6c4f4f393fad8d07e56 Author: Glenn Morris Date: Wed May 24 13:11:32 2017 -0400 Don't autoload new dns-mode command * lisp/textmodes/dns-mode.el (dns-mode-ipv6-to-nibbles): Remove autoload cookie. diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el index 7bdadbfe6f..72eb66b571 100644 --- a/lisp/textmodes/dns-mode.el +++ b/lisp/textmodes/dns-mode.el @@ -256,7 +256,6 @@ This function is run from `before-save-hook'." ;; We return nil in case this is used in write-contents-functions. nil))) -;;;###autoload (defun dns-mode-ipv6-to-nibbles (&optional negate-prefix) "Convert an IPv6 address around or before point. Replace the address by its ip6.arpa-representation for use in commit 7dfe682ee7e905b6e3d4513e7cef0798bc2de0f0 Author: Stefan Monnier Date: Wed May 24 11:55:13 2017 -0400 * src/fns.c (sxhash): Fix records hashing (bug#27057, bug#26639) (sxhash_vector): Make it work on pseudo vectors as well. (sxhash): Treat records like vectors. diff --git a/src/fns.c b/src/fns.c index 0332ab5dad..6610d2a6d0 100644 --- a/src/fns.c +++ b/src/fns.c @@ -4289,7 +4289,7 @@ sxhash_list (Lisp_Object list, int depth) } -/* Return a hash for vector VECTOR. DEPTH is the current depth in +/* Return a hash for (pseudo)vector VECTOR. DEPTH is the current depth in the Lisp structure. */ static EMACS_UINT @@ -4298,7 +4298,7 @@ sxhash_vector (Lisp_Object vec, int depth) EMACS_UINT hash = ASIZE (vec); int i, n; - n = min (SXHASH_MAX_LEN, ASIZE (vec)); + n = min (SXHASH_MAX_LEN, hash & PSEUDOVECTOR_FLAG ? PVSIZE (vec) : hash); for (i = 0; i < n; ++i) { EMACS_UINT hash2 = sxhash (AREF (vec, i), depth + 1); @@ -4353,11 +4353,11 @@ sxhash (Lisp_Object obj, int depth) /* This can be everything from a vector to an overlay. */ case Lisp_Vectorlike: - if (VECTORP (obj)) + if (VECTORP (obj) || RECORDP (obj)) /* According to the CL HyperSpec, two arrays are equal only if they are `eq', except for strings and bit-vectors. In Emacs, this works differently. We have to compare element - by element. */ + by element. Same for records. */ hash = sxhash_vector (obj, depth); else if (BOOL_VECTOR_P (obj)) hash = sxhash_bool_vector (obj); commit ac36012dc2e751788861b37e77f99d66c4da352a Author: Michael Albinus Date: Wed May 24 16:17:59 2017 +0200 Adapt tramp-tests.el according to new defstruct * test/lisp/net/tramp-tests.el (tramp-test03-file-name-defaults): Fix test according to new defstruct. (tramp-test29-environment-variables-and-port-numbers): Expect it now as passed. Cleanup at the end. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 0106807a9a..7a12aae1bf 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -1510,7 +1510,7 @@ handled properly. BODY shall not contain a timeout." (ert-deftest tramp-test03-file-name-defaults () "Check default values for some methods." ;; Default values in tramp-adb.el. - (should (string-equal (file-remote-p "/adb::" 'host) "")) + (should (string-equal (file-remote-p "/adb::" 'host) nil)) ;; Default values in tramp-ftp.el. (should (string-equal (file-remote-p "/-:ftp.host:" 'method) "ftp")) (dolist (u '("ftp" "anonymous")) @@ -1529,7 +1529,6 @@ handled properly. BODY shall not contain a timeout." (should (string-equal (file-remote-p (format "/%s::" m) 'user) (user-login-name)))) ;; Default values in tramp-smb.el. - (should (string-equal (file-remote-p "/-:user%domain@host:" 'method) "smb")) (should (string-equal (file-remote-p "/smb::" 'user) nil))) (ert-deftest tramp-test04-substitute-in-file-name () @@ -2926,8 +2925,6 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." ;; This test is inspired by Bug#27009. (ert-deftest tramp-test29-environment-variables-and-port-numbers () "Check that two connections with separate ports are different." - ;; Mark as failed until bug has been fixed. - :expected-result :failed (skip-unless (tramp--test-enabled)) ;; We test it only for the mock-up connection; otherwise there might ;; be problems with the used ports. @@ -2938,26 +2935,31 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." "mock" (file-remote-p tramp-test-temporary-file-directory 'method)))) ;; We force a reconnect, in order to have a clean environment. - (dolist (dir - `(,tramp-test-temporary-file-directory - "/mock:localhost#11111:" "/mock:localhost#22222:")) + (dolist (dir `(,tramp-test-temporary-file-directory + "/mock:localhost#11111:" "/mock:localhost#22222:")) (tramp-cleanup-connection (tramp-dissect-file-name dir) 'keep-debug 'keep-password)) - (dolist (port '(11111 22222)) - (let* ((default-directory - (format "/mock:localhost#%d:%s" port temporary-file-directory)) - (shell-file-name "/bin/sh") - (envvar (concat "VAR_" (upcase (md5 (current-time-string))))) - ;; We cannot use `process-environment', because this would - ;; be applied in `process-file'. - (tramp-remote-process-environment - (cons - (format "%s=%d" envvar port) tramp-remote-process-environment))) - (should - (string-equal - (number-to-string port) - (shell-command-to-string (format "echo -n $%s" envvar))))))) + (unwind-protect + (dolist (port '(11111 22222)) + (let* ((default-directory + (format "/mock:localhost#%d:%s" port temporary-file-directory)) + (shell-file-name "/bin/sh") + (envvar (concat "VAR_" (upcase (md5 (current-time-string))))) + ;; We cannot use `process-environment', because this + ;; would be applied in `process-file'. + (tramp-remote-process-environment + (cons + (format "%s=%d" envvar port) + tramp-remote-process-environment))) + (should + (string-equal + (number-to-string port) + (shell-command-to-string (format "echo -n $%s" envvar)))))) + + ;; Cleanup. + (dolist (dir '("/mock:localhost#11111:" "/mock:localhost#22222:")) + (tramp-cleanup-connection (tramp-dissect-file-name dir))))) ;; The functions were introduced in Emacs 26.1. (ert-deftest tramp-test30-explicit-shell-file-name () commit dca22e86e02d16a31128c163925b13404f777c0f Author: Michael Albinus Date: Wed May 24 16:16:53 2017 +0200 Introduce a defstruct `tramp-file-name' as central data structure. This solves also Bug#27009. * lisp/net/tramp.el (tramp-current-domain) (tramp-current-port): New defvars. (tramp-file-name): New defstruct. (tramp-file-name-user-domain, tramp-file-name-host-port) (tramp-file-name-equal-p): New defuns. (tramp-file-name-p, tramp-file-name-method) (tramp-file-name-user, tramp-file-name-host) (tramp-file-name-localname, tramp-file-name-hop) (tramp-file-name-real-user, tramp-file-name-domain) (tramp-file-name-real-host, tramp-file-name-port): Remove defuns. They are provided by the defstruct, or not needed anymore. (tramp-dissect-file-name, tramp-buffer-name) (tramp-make-tramp-file-name, tramp-get-buffer) (tramp-set-connection-local-variables) (tramp-debug-buffer-name, tramp-message) (tramp-error-with-buffer, with-parsed-tramp-file-name) (tramp-completion-dissect-file-name1) (tramp-handle-file-name-as-directory) (tramp-handle-file-name-directory) (tramp-handle-file-remote-p, tramp-handle-file-symlink-p) (tramp-handle-find-backup-file-name) (tramp-handle-insert-file-contents, tramp-process-actions) (tramp-check-cached-permissions, tramp-local-host-p) (tramp-get-remote-tmpdir, tramp-call-process) (tramp-call-process-region, tramp-read-passwd) (tramp-clear-passwd): * lisp/net/tramp-adb.el (tramp-adb-parse-device-names) (tramp-adb-handle-expand-file-name) (tramp-adb-handle-file-truename, tramp-adb-handle-copy-file) (tramp-adb-handle-process-file) (tramp-adb-maybe-open-connection): * lisp/net/tramp-cache.el (tramp-get-hash-table) (tramp-get-file-property, tramp-set-file-property) (tramp-flush-file-property, tramp-flush-directory-property) (tramp-get-connection-property) (tramp-set-connection-property, tramp-connection-property-p) (tramp-flush-connection-property, tramp-cache-print) (tramp-list-connections, tramp-dump-connection-properties) (tramp-parse-connection-properties): * lisp/net/tramp-cmds.el (tramp-cleanup-connection): * lisp/net/tramp-ftp.el (tramp-ftp-file-name-handler): * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-expand-file-name) (tramp-gvfs-url-file-name, tramp-gvfs-handler-askpassword) (tramp-gvfs-handler-mounted-unmounted) (tramp-gvfs-mount-spec, tramp-gvfs-get-remote-uid) (tramp-gvfs-get-remote-gid) (tramp-gvfs-maybe-open-connection): * lisp/net/tramp-sh.el (tramp-sh-handle-file-truename) (tramp-do-copy-or-rename-file-out-of-band) (tramp-sh-handle-expand-file-name) (tramp-sh-handle-start-file-process) (tramp-sh-handle-process-file, tramp-compute-multi-hops) (tramp-maybe-open-connection) (tramp-make-copy-program-file-name, tramp-get-remote-path) (tramp-get-inline-coding): * lisp/net/tramp-smb.el (tramp-smb-handle-copy-directory) (tramp-smb-handle-expand-file-name) (tramp-smb-handle-file-acl, tramp-smb-handle-process-file) (tramp-smb-handle-set-file-acl) (tramp-smb-maybe-open-connection): Adapt according to defstruct. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 2825532c52..1c894c9b0c 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -199,8 +199,9 @@ pass to the OPERATION." ;; That's why we use `start-process'. (let ((p (start-process tramp-adb-program (current-buffer) tramp-adb-program "devices")) - (v (vector tramp-adb-method tramp-current-user - tramp-current-host nil nil)) + (v (tramp-make-tramp-file-name + tramp-adb-method tramp-current-user nil + tramp-current-host nil nil nil)) result) (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) (process-put p 'adjust-window-size-function 'ignore) @@ -242,7 +243,7 @@ pass to the OPERATION." ;; be problems with UNC shares or Cygwin mounts. (let ((default-directory (tramp-compat-temporary-file-directory))) (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-drop-volume-letter (tramp-run-real-handler 'expand-file-name (list localname)))))))) @@ -261,7 +262,7 @@ pass to the OPERATION." "%s%s" (with-parsed-tramp-file-name (expand-file-name filename) nil (tramp-make-tramp-file-name - method user host + method user domain host port (with-tramp-file-property v localname "file-truename" (let ((result nil)) ; result steps in reverse order (tramp-message v 4 "Finding true name for `%s'" filename) @@ -289,7 +290,7 @@ pass to the OPERATION." (tramp-compat-file-attribute-type (file-attributes (tramp-make-tramp-file-name - method user host + method user domain host port (mapconcat 'identity (append '("") (reverse result) @@ -687,7 +688,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." newname (expand-file-name newname)) (if (file-directory-p filename) - (tramp-file-name-handler 'copy-directory filename newname keep-date t) + (copy-directory filename newname keep-date t) (let ((t1 (tramp-tramp-file-p filename)) (t2 (tramp-tramp-file-p newname))) @@ -815,7 +816,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq input (with-parsed-tramp-file-name infile nil localname)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) - tmpinput (tramp-make-tramp-file-name method user host input)) + tmpinput (tramp-make-tramp-file-name + method user domain host port input)) (copy-file infile tmpinput t))) (when input (setq command (format "%s <%s" command input))) @@ -849,7 +851,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; file must be deleted after execution. (setq stderr (tramp-make-tramp-temp-file v) tmpstderr (tramp-make-tramp-file-name - method user host stderr)))) + method user domain host port stderr)))) ;; stderr to be discarded. ((null (cadr destination)) (setq stderr "/dev/null")))) @@ -1199,8 +1201,7 @@ connection if a previous connection has died for some reason." (device (tramp-adb-get-device vec))) ;; Set variables for proper tracing in `tramp-adb-parse-device-names'. - (setq tramp-current-method (tramp-file-name-method vec) - tramp-current-user (tramp-file-name-user vec) + (setq tramp-current-user (tramp-file-name-user vec) tramp-current-host (tramp-file-name-host vec)) ;; Maybe we know already that "su" is not supported. We cannot diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index 64268cfc25..a9a1c6615e 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -27,9 +27,9 @@ ;; An implementation of information caching for remote files. -;; Each connection, identified by a vector [method user host -;; localname] or by a process, has a unique cache. We distinguish 3 -;; kind of caches, depending on the key: +;; Each connection, identified by a `tramp-file-name' structure or by +;; a process, has a unique cache. We distinguish 3 kind of caches, +;; depending on the key: ;; ;; - localname is NIL. This are reusable properties. Examples: ;; "remote-shell" identifies the POSIX shell to be called on the @@ -94,12 +94,14 @@ matching entries of `tramp-connection-properties'." (or (gethash key tramp-cache-data) (let ((hash (puthash key (make-hash-table :test 'equal) tramp-cache-data))) - (when (vectorp key) + (when (tramp-file-name-p key) (dolist (elt tramp-connection-properties) (when (string-match (or (nth 0 elt) "") (tramp-make-tramp-file-name - (aref key 0) (aref key 1) (aref key 2) nil)) + (tramp-file-name-method key) (tramp-file-name-user key) + (tramp-file-name-domain key) (tramp-file-name-host key) + (tramp-file-name-port key) nil)) (tramp-set-connection-property key (nth 1 elt) (nth 2 elt))))) hash))) @@ -107,11 +109,12 @@ matching entries of `tramp-connection-properties'." (defun tramp-get-file-property (key file property default) "Get the PROPERTY of FILE from the cache context of KEY. Returns DEFAULT if not set." - ;; Unify localname. Remove hop from vector. - (setq file (tramp-compat-file-name-unquote file)) - (setq key (copy-sequence key)) - (aset key 3 (tramp-run-real-handler 'directory-file-name (list file))) - (aset key 4 nil) + ;; Unify localname. Remove hop from `tramp-file-name' structure. + (setq file (tramp-compat-file-name-unquote file) + key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) + (tramp-run-real-handler 'directory-file-name (list file)) + (tramp-file-name-hop key) nil) (let* ((hash (tramp-get-hash-table key)) (value (when (hash-table-p hash) (gethash property hash)))) (if @@ -141,11 +144,12 @@ Returns DEFAULT if not set." (defun tramp-set-file-property (key file property value) "Set the PROPERTY of FILE to VALUE, in the cache context of KEY. Returns VALUE." - ;; Unify localname. Remove hop from vector. - (setq file (tramp-compat-file-name-unquote file)) - (setq key (copy-sequence key)) - (aset key 3 (tramp-run-real-handler 'directory-file-name (list file))) - (aset key 4 nil) + ;; Unify localname. Remove hop from `tramp-file-name' structure. + (setq file (tramp-compat-file-name-unquote file) + key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) + (tramp-run-real-handler 'directory-file-name (list file)) + (tramp-file-name-hop key) nil) (let ((hash (tramp-get-hash-table key))) ;; We put the timestamp there. (puthash property (cons (current-time) value) hash) @@ -162,11 +166,11 @@ Returns VALUE." (let* ((file (tramp-run-real-handler 'directory-file-name (list file))) (truename (tramp-get-file-property key file "file-truename" nil))) - ;; Unify localname. Remove hop from vector. - (setq file (tramp-compat-file-name-unquote file)) - (setq key (copy-sequence key)) - (aset key 3 file) - (aset key 4 nil) + ;; Unify localname. Remove hop from `tramp-file-name' structure. + (setq file (tramp-compat-file-name-unquote file) + key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) file + (tramp-file-name-hop key) nil) (tramp-message key 8 "%s" file) (remhash key tramp-cache-data) ;; Remove file properties of symlinks. @@ -185,7 +189,8 @@ Remove also properties of all files in subdirectories." (tramp-message key 8 "%s" directory) (maphash (lambda (key _value) - (when (and (stringp (tramp-file-name-localname key)) + (when (and (tramp-file-name-p key) + (stringp (tramp-file-name-localname key)) (string-match (regexp-quote directory) (tramp-file-name-localname key))) (remhash key tramp-cache-data))) @@ -232,15 +237,15 @@ This is suppressed for temporary buffers." (defun tramp-get-connection-property (key property default) "Get the named PROPERTY for the connection. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine. If the value is not set for the -connection, returns DEFAULT." - ;; Unify key by removing localname and hop from vector. Work with a - ;; copy in order to avoid side effects. - (when (vectorp key) - (setq key (copy-sequence key)) - (aset key 3 nil) - (aset key 4 nil)) +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine. If the +value is not set for the connection, returns DEFAULT." + ;; Unify key by removing localname and hop from `tramp-file-name' + ;; structure. Work with a copy in order to avoid side effects. + (when (tramp-file-name-p key) + (setq key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) nil + (tramp-file-name-hop key) nil)) (let* ((hash (tramp-get-hash-table key)) (value ;; If the key is an auxiliary process object, check whether @@ -257,15 +262,15 @@ connection, returns DEFAULT." (defun tramp-set-connection-property (key property value) "Set the named PROPERTY of a connection to VALUE. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine. PROPERTY is set persistent when -KEY is a vector." - ;; Unify key by removing localname and hop from vector. Work with a - ;; copy in order to avoid side effects. - (when (vectorp key) - (setq key (copy-sequence key)) - (aset key 3 nil) - (aset key 4 nil)) +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine. +PROPERTY is set persistent when KEY is a `tramp-file-name' structure." + ;; Unify key by removing localname and hop from `tramp-file-name' + ;; structure. Work with a copy in order to avoid side effects. + (when (tramp-file-name-p key) + (setq key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) nil + (tramp-file-name-hop key) nil)) (let ((hash (tramp-get-hash-table key))) (puthash property value hash) (setq tramp-cache-data-changed t) @@ -276,22 +281,22 @@ KEY is a vector." (defun tramp-connection-property-p (key property) "Check whether named PROPERTY of a connection is defined. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine." +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine." (not (eq (tramp-get-connection-property key property 'undef) 'undef))) ;;;###tramp-autoload (defun tramp-flush-connection-property (key) "Remove all properties identified by KEY. KEY identifies the connection, it is either a process or a -vector. A special case is nil, which is used to cache connection -properties of the local machine." - ;; Unify key by removing localname and hop from vector. Work with a - ;; copy in order to avoid side effects. - (when (vectorp key) - (setq key (copy-sequence key)) - (aset key 3 nil) - (aset key 4 nil)) +`tramp-file-name' structure. A special case is nil, which is +used to cache connection properties of the local machine." + ;; Unify key by removing localname and hop from `tramp-file-name' + ;; structure. Work with a copy in order to avoid side effects. + (when (tramp-file-name-p key) + (setq key (copy-tramp-file-name key)) + (setf (tramp-file-name-localname key) nil + (tramp-file-name-hop key) nil)) (tramp-message key 7 "%s %s" key (let ((hash (gethash key tramp-cache-data)) @@ -310,7 +315,16 @@ properties of the local machine." (maphash (lambda (key value) ;; Remove text properties from KEY and VALUE. - (when (vectorp key) + ;; `cl-struct-slot-*' functions exist since Emacs 25 only; we + ;; ignore errors. + (when (tramp-file-name-p key) + ;; (dolist + ;; (slot + ;; (mapcar 'car (cdr (cl-struct-slot-info 'tramp-file-name)))) + ;; (when (stringp (cl-struct-slot-value 'tramp-file-name slot key)) + ;; (setf (cl-struct-slot-value 'tramp-file-name slot key) + ;; (substring-no-properties + ;; (cl-struct-slot-value 'tramp-file-name slot key)))))) (dotimes (i (length key)) (when (stringp (aref key i)) (aset key i (substring-no-properties (aref key i)))))) @@ -335,11 +349,12 @@ properties of the local machine." ;;;###tramp-autoload (defun tramp-list-connections () - "Return a list of all known connection vectors according to `tramp-cache'." + "Return all known `tramp-file-name' structs according to `tramp-cache'." (let (result tramp-verbose) (maphash (lambda (key _value) - (when (and (vectorp key) (null (aref key 3)) + (when (and (tramp-file-name-p key) + (null (tramp-file-name-localname key)) (tramp-connection-property-p key "process-buffer")) (add-to-list 'result key))) tramp-cache-data) @@ -361,7 +376,7 @@ properties of the local machine." ;; possibility to use another login name later on. (maphash (lambda (key value) - (if (and (vectorp key) + (if (and (tramp-file-name-p key) (not (tramp-file-name-localname key)) (not (gethash "login-as" value))) (progn @@ -402,7 +417,7 @@ for all methods. Resulting data are derived from connection history." (let (res) (maphash (lambda (key _value) - (if (and (vectorp key) + (if (and (tramp-file-name-p key) (string-equal method (tramp-file-name-method key)) (not (tramp-file-name-localname key))) (push (list (tramp-file-name-user key) @@ -427,12 +442,13 @@ for all methods. Resulting data are derived from connection history." element key item) (while (setq element (pop list)) (setq key (pop element)) - (while (setq item (pop element)) - ;; We set only values which are not contained in - ;; `tramp-connection-properties'. The cache is - ;; initialized properly by side effect. - (unless (tramp-connection-property-p key (car item)) - (tramp-set-connection-property key (pop item) (car item)))))) + (when (tramp-file-name-p key) + (while (setq item (pop element)) + ;; We set only values which are not contained in + ;; `tramp-connection-properties'. The cache is + ;; initialized properly by side effect. + (unless (tramp-connection-property-p key (car item)) + (tramp-set-connection-property key (pop item) (car item))))))) (setq tramp-cache-data-changed nil)) (file-error ;; Most likely because the file doesn't exist yet. No message. diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 4007b65c3a..4c5a12d33b 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -85,7 +85,9 @@ When called interactively, a Tramp connection has to be selected." (tramp-make-tramp-file-name (tramp-file-name-method x) (tramp-file-name-user x) + (tramp-file-name-domain x) (tramp-file-name-host x) + (tramp-file-name-port x) (tramp-file-name-localname x))) (tramp-list-connections))) name) diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index 8d1900d4e3..44a4ccadac 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el @@ -145,7 +145,7 @@ pass to the OPERATION." ((memq operation '(file-directory-p file-exists-p)) (if (apply 'ange-ftp-hook-function operation args) (let ((v (tramp-dissect-file-name (car args) t))) - (aset v 0 tramp-ftp-method) + (setf (tramp-file-name-method v) tramp-ftp-method) (tramp-set-connection-property v "started" t)) nil)) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index cf3906aef3..ad9bd819c0 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -807,7 +807,8 @@ file names." ;; If there is a default location, expand tilde. (when (string-match "\\`\\(~\\)\\(/\\|\\'\\)" localname) (save-match-data - (tramp-gvfs-maybe-open-connection (vector method user host "/" hop))) + (tramp-gvfs-maybe-open-connection + (tramp-make-tramp-file-name method user domain host port "/" hop))) (setq localname (replace-match (tramp-get-connection-property v "default-location" "~") @@ -831,7 +832,7 @@ file names." ;; No tilde characters in file name, do normal ;; `expand-file-name' (this does "/./" and "/../"). (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-run-real-handler 'expand-file-name (list localname)))))) @@ -1249,7 +1250,7 @@ file-notify events." (concat (match-string 2 user) ";" (match-string 1 user)))) (url-parse-make-urlobj method (and user (url-hexify-string user)) nil - (tramp-file-name-real-host v) (tramp-file-name-port v) + (tramp-file-name-host v) (tramp-file-name-port v) (and localname (url-hexify-string localname)) nil nil t)) (url-parse-make-urlobj "file" nil nil nil nil @@ -1329,12 +1330,12 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." t ;; password handled. nil ;; no abort of D-Bus. password - (tramp-file-name-real-user l) + (tramp-file-name-user l) domain nil ;; not anonymous. 0) ;; no password save. ;; No password provided. - (list nil t "" (tramp-file-name-real-user l) domain nil 0))) + (list nil t "" (tramp-file-name-user l) domain nil 0))) ;; When QUIT is raised, we shall return this information to D-Bus. (quit (list nil t "" "" "" nil 0))))) @@ -1420,7 +1421,7 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"." (unless (zerop (length port)) (setq host (concat host tramp-prefix-port-format port))) (with-parsed-tramp-file-name - (tramp-make-tramp-file-name method user host "") nil + (tramp-make-tramp-file-name method user domain host port "") nil (tramp-message v 6 "%s %s" signal-name (tramp-gvfs-stringify-dbus-message mount-info)) @@ -1533,9 +1534,9 @@ It was \"a(say)\", but has changed to \"a{sv})\"." (defun tramp-gvfs-mount-spec (vec) "Return a mount-spec for \"org.gtk.vfs.MountTracker.mountLocation\"." (let* ((method (tramp-file-name-method vec)) - (user (tramp-file-name-real-user vec)) + (user (tramp-file-name-user vec)) (domain (tramp-file-name-domain vec)) - (host (tramp-file-name-real-host vec)) + (host (tramp-file-name-host vec)) (port (tramp-file-name-port vec)) (localname (tramp-file-name-unquote-localname vec)) (share (when (string-match "^/?\\([^/]+\\)" localname) @@ -1591,7 +1592,9 @@ ID-FORMAT valid values are `string' and `integer'." (with-tramp-connection-property vec (format "uid-%s" id-format) (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (localname (tramp-get-connection-property vec "default-location" nil))) (cond @@ -1599,7 +1602,8 @@ ID-FORMAT valid values are `string' and `integer'." (localname (tramp-compat-file-attribute-user-id (file-attributes - (tramp-make-tramp-file-name method user host localname) id-format))) + (tramp-make-tramp-file-name method user domain host port localname) + id-format))) ((equal id-format 'integer) tramp-unknown-id-integer) ((equal id-format 'string) tramp-unknown-id-string))))) @@ -1609,14 +1613,17 @@ ID-FORMAT valid values are `string' and `integer'." (with-tramp-connection-property vec (format "gid-%s" id-format) (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (localname (tramp-get-connection-property vec "default-location" nil))) (cond (localname (tramp-compat-file-attribute-group-id (file-attributes - (tramp-make-tramp-file-name method user host localname) id-format))) + (tramp-make-tramp-file-name method user domain host port localname) + id-format))) ((equal id-format 'integer) tramp-unknown-id-integer) ((equal id-format 'string) tramp-unknown-id-string))))) @@ -1644,11 +1651,13 @@ connection if a previous connection has died for some reason." (unless (tramp-gvfs-connection-mounted-p vec) (let* ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (localname (tramp-file-name-unquote-localname vec)) (object-path (tramp-gvfs-object-path - (tramp-make-tramp-file-name method user host "")))) + (tramp-make-tramp-file-name method user domain host port "")))) (when (and (string-equal method "afp") (string-equal localname "/")) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 999de8e850..4b89c17347 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1122,7 +1122,7 @@ target of the symlink differ." "%s%s" (with-parsed-tramp-file-name (expand-file-name filename) nil (tramp-make-tramp-file-name - method user host + method user domain host port (with-tramp-file-property v localname "file-truename" (let ((result nil) ; result steps in reverse order (quoted (tramp-compat-file-name-quoted-p localname)) @@ -1174,7 +1174,7 @@ target of the symlink differ." (tramp-compat-file-attribute-type (file-attributes (tramp-make-tramp-file-name - method user host + method user domain host port (mapconcat 'identity (append '("") (reverse result) @@ -2335,7 +2335,7 @@ The method used must be an out-of-band method." (let* ((t1 (tramp-tramp-file-p filename)) (t2 (tramp-tramp-file-p newname)) (orig-vec (tramp-dissect-file-name (if t1 filename newname))) - copy-program copy-args copy-env copy-keep-date port listener spec + copy-program copy-args copy-env copy-keep-date listener spec options source target remote-copy-program remote-copy-args) (with-parsed-tramp-file-name (if t1 filename newname) nil @@ -2368,7 +2368,7 @@ The method used must be an out-of-band method." tramp-current-user (or (tramp-file-name-user v) (tramp-get-connection-property v "login-as" nil)) - tramp-current-host (tramp-file-name-real-host v)) + tramp-current-host (tramp-file-name-host v)) ;; Check which ones of source and target are Tramp files. (setq source (funcall @@ -2383,10 +2383,6 @@ The method used must be an out-of-band method." (tramp-make-copy-program-file-name v) (tramp-unquote-shell-quote-argument newname))) - ;; Check for host and port number. - (setq host (tramp-file-name-real-host v) - port (tramp-file-name-port v)) - ;; Check for user. There might be an interactive setting. (setq user (or (tramp-file-name-user v) (tramp-get-connection-property v "login-as" nil))) @@ -2809,7 +2805,7 @@ the result will be a local, non-Tramp, file name." ;; be problems with UNC shares or Cygwin mounts. (let ((default-directory (tramp-compat-temporary-file-directory))) (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-drop-volume-letter (tramp-run-real-handler 'expand-file-name (list localname))) @@ -2861,7 +2857,9 @@ the result will be a local, non-Tramp, file name." (tramp-make-tramp-file-name (tramp-file-name-method v) (tramp-file-name-user v) + (tramp-file-name-domain v) (tramp-file-name-host v) + (tramp-file-name-port v) (tramp-file-name-localname v)) tramp-initial-end-of-output)) ;; We use as environment the difference to toplevel @@ -2999,7 +2997,8 @@ the result will be a local, non-Tramp, file name." (setq input (with-parsed-tramp-file-name infile nil localname)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) - tmpinput (tramp-make-tramp-file-name method user host input)) + tmpinput + (tramp-make-tramp-file-name method user domain host port input)) (copy-file infile tmpinput t))) (when input (setq command (format "%s <%s" command input))) @@ -3033,7 +3032,7 @@ the result will be a local, non-Tramp, file name." ;; file must be deleted after execution. (setq stderr (tramp-make-tramp-temp-file v) tmpstderr (tramp-make-tramp-file-name - method user host stderr)))) + method user domain host port stderr)))) ;; stderr to be discarded. ((null (cadr destination)) (setq stderr "/dev/null")))) @@ -4546,7 +4545,7 @@ Goes through the list `tramp-inline-compress-commands'." ;; host name. (let* ((v (car target-alist)) (method (tramp-file-name-method v)) - (host (tramp-file-name-real-host v))) + (host (tramp-file-name-host v))) (unless (or ;; There are multi-hops. @@ -4623,8 +4622,8 @@ connection if a previous connection has died for some reason." ;; If Tramp opens the same connection within a short time frame, ;; there is a problem. We shall signal this. (unless (or (tramp-compat-process-live-p p) - (not (equal (butlast (append vec nil) 2) - (car tramp-current-connection))) + (not (tramp-file-name-equal-p + vec (car tramp-current-connection))) (> (tramp-time-diff (current-time) (cdr tramp-current-connection)) (or tramp-connection-min-time-diff 0))) @@ -4721,8 +4720,7 @@ connection if a previous connection has died for some reason." (set-process-sentinel p 'tramp-process-sentinel) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) - (setq tramp-current-connection - (cons (butlast (append vec nil) 2) (current-time)) + (setq tramp-current-connection (cons vec (current-time)) tramp-current-host (system-name)) (tramp-message @@ -5104,7 +5102,7 @@ Return ATTR." "Create a file name suitable for `scp', `pscp', or `nc' and workalikes." (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) - (host (tramp-file-name-real-host vec)) + (host (tramp-file-name-host vec)) (localname (directory-file-name (tramp-file-name-unquote-localname vec)))) (when (string-match tramp-ipv6-regexp host) @@ -5218,7 +5216,9 @@ Nonexistent directories are removed from spec." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) x)) x)) remote-path))))) @@ -5636,14 +5636,14 @@ function cell is returned to be applied on a buffer." (let ((coding-system-for-write 'binary) (coding-system-for-read 'binary)) (apply - 'tramp-call-process-region ,vec (point-min) (point-max) + 'tramp-call-process-region ',vec (point-min) (point-max) (car (split-string ,compress)) t t nil (cdr (split-string ,compress))))) `(lambda (beg end) (let ((coding-system-for-write 'binary) (coding-system-for-read 'binary)) (apply - 'tramp-call-process-region ,vec beg end + 'tramp-call-process-region ',vec beg end (car (split-string ,compress)) t t nil (cdr (split-string ,compress)))) (,coding (point-min) (point-max))))) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 12eb367951..7b2a1ba874 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -53,12 +53,6 @@ ;; Another guess. We might implement a better check later on. (tramp-case-insensitive t)))) -;; Add a default for `tramp-default-method-alist'. Rule: If there is -;; a domain in USER, it must be the SMB method. -;;;###tramp-autoload -(add-to-list 'tramp-default-method-alist - `(nil ,tramp-prefix-domain-regexp ,tramp-smb-method)) - ;; Add a default for `tramp-default-user-alist'. Rule: For the SMB method, ;; the anonymous user is chosen. ;;;###tramp-autoload @@ -449,15 +443,11 @@ pass to the OPERATION." (if (not (file-directory-p newname)) (make-directory newname parents)) - (setq tramp-current-method (tramp-file-name-method v) - tramp-current-user (tramp-file-name-user v) - tramp-current-host (tramp-file-name-real-host v)) + (setq tramp-current-method method + tramp-current-user user + tramp-current-host host) - (let* ((real-user (tramp-file-name-real-user v)) - (real-host (tramp-file-name-real-host v)) - (domain (tramp-file-name-domain v)) - (port (tramp-file-name-port v)) - (share (tramp-smb-get-share v)) + (let* ((share (tramp-smb-get-share v)) (localname (file-name-as-directory (replace-regexp-in-string "\\\\" "/" (tramp-smb-get-localname v)))) @@ -465,10 +455,10 @@ pass to the OPERATION." (expand-file-name tramp-temp-name-prefix (tramp-compat-temporary-file-directory)))) - (args (list (concat "//" real-host "/" share) "-E"))) + (args (list (concat "//" host "/" share) "-E"))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -708,7 +698,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq localname (replace-match (if (zerop (length (match-string 1 localname))) - (tramp-file-name-real-user v) + user (match-string 1 localname)) nil nil localname))) ;; Make the file name absolute. @@ -717,7 +707,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; No tilde characters in file name, do normal ;; `expand-file-name' (this does "/./" and "/../"). (tramp-make-tramp-file-name - method user host + method user domain host port (tramp-run-real-handler 'expand-file-name (list localname)))))) (defun tramp-smb-action-get-acl (proc vec) @@ -744,21 +734,17 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (with-tramp-file-property v localname "file-acl" (when (executable-find tramp-smb-acl-program) - (setq tramp-current-method (tramp-file-name-method v) - tramp-current-user (tramp-file-name-user v) - tramp-current-host (tramp-file-name-real-host v)) + (setq tramp-current-method method + tramp-current-user user + tramp-current-host host) - (let* ((real-user (tramp-file-name-real-user v)) - (real-host (tramp-file-name-real-host v)) - (domain (tramp-file-name-domain v)) - (port (tramp-file-name-port v)) - (share (tramp-smb-get-share v)) + (let* ((share (tramp-smb-get-share v)) (localname (replace-regexp-in-string "\\\\" "/" (tramp-smb-get-localname v))) - (args (list (concat "//" real-host "/" share) "-E"))) + (args (list (concat "//" host "/" share) "-E"))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -1179,7 +1165,8 @@ target of the symlink differ." (setq input (with-parsed-tramp-file-name infile nil localname)) ;; INFILE must be copied to remote host. (setq input (tramp-make-tramp-temp-file v) - tmpinput (tramp-make-tramp-file-name method user host input)) + tmpinput + (tramp-make-tramp-file-name method user domain host port input)) (copy-file infile tmpinput t)) ;; Transform input into a filename powershell does understand. (setq input (format "//%s%s" host input))) @@ -1337,24 +1324,20 @@ target of the symlink differ." (ignore-errors (with-parsed-tramp-file-name filename nil (when (and (stringp acl-string) (executable-find tramp-smb-acl-program)) - (setq tramp-current-method (tramp-file-name-method v) - tramp-current-user (tramp-file-name-user v) - tramp-current-host (tramp-file-name-real-host v)) + (setq tramp-current-method method + tramp-current-user user + tramp-current-host host) (tramp-set-file-property v localname "file-acl" 'undef) - (let* ((real-user (tramp-file-name-real-user v)) - (real-host (tramp-file-name-real-host v)) - (domain (tramp-file-name-domain v)) - (port (tramp-file-name-port v)) - (share (tramp-smb-get-share v)) + (let* ((share (tramp-smb-get-share v)) (localname (replace-regexp-in-string "\\\\" "/" (tramp-smb-get-localname v))) - (args (list (concat "//" real-host "/" share) "-E" "-S" + (args (list (concat "//" host "/" share) "-E" "-S" (replace-regexp-in-string "\n" "," acl-string)))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) @@ -1845,24 +1828,22 @@ If ARGUMENT is non-nil, use it as argument for (when buf (with-current-buffer buf (erase-buffer))) (when (and p (processp p)) (delete-process p)) - (let* ((user (tramp-file-name-user vec)) - (host (tramp-file-name-host vec)) - (real-user (tramp-file-name-real-user vec)) - (real-host (tramp-file-name-real-host vec)) - (domain (tramp-file-name-domain vec)) - (port (tramp-file-name-port vec)) + (let* ((user (tramp-file-name-user vec)) + (host (tramp-file-name-host vec)) + (domain (tramp-file-name-domain vec)) + (port (tramp-file-name-port vec)) args) (cond (argument - (setq args (list (concat "//" real-host)))) + (setq args (list (concat "//" host)))) (share - (setq args (list (concat "//" real-host "/" share)))) + (setq args (list (concat "//" host "/" share)))) (t - (setq args (list "-g" "-L" real-host )))) + (setq args (list "-g" "-L" host )))) - (if (not (zerop (length real-user))) - (setq args (append args (list "-U" real-user))) + (if (not (zerop (length user))) + (setq args (append args (list "-U" user))) (setq args (append args (list "-N")))) (when domain (setq args (append args (list "-W" domain)))) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 70abb89194..c481ec66ce 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1099,9 +1099,15 @@ means to use always cached values for the directory contents." (defvar tramp-current-user nil "Remote login name for this *tramp* buffer.") +(defvar tramp-current-domain nil + "Remote domain name for this *tramp* buffer.") + (defvar tramp-current-host nil "Remote host for this *tramp* buffer.") +(defvar tramp-current-port nil + "Remote port for this *tramp* buffer.") + (defvar tramp-current-connection nil "Last connection timestamp.") @@ -1128,6 +1134,37 @@ calling HANDLER.") ;; internal data structure. Convenience functions for internal ;; data structure. +;; The basic structure for remote file names. We use a list, +;; otherwise the test in `tramp-cache-data' fails. +(cl-defstruct (tramp-file-name (:type list) :named) + method user domain host port localname hop) + +(defun tramp-file-name-user-domain (vec) + "Return user and domain components of VEC." + (when (or (tramp-file-name-user vec) (tramp-file-name-domain vec)) + (concat (tramp-file-name-user vec) + (and (tramp-file-name-domain vec) + tramp-prefix-domain-format) + (tramp-file-name-domain vec)))) + +(defun tramp-file-name-host-port (vec) + "Return host and port components of VEC." + (when (or (tramp-file-name-host vec) (tramp-file-name-port vec)) + (concat (tramp-file-name-host vec) + (and (tramp-file-name-port vec) + tramp-prefix-port-format) + (tramp-file-name-port vec)))) + +(defun tramp-file-name-equal-p (vec1 vec2) + "Check, whether VEC1 and VEC2 denote the same `tramp-file-name'." + (and (tramp-file-name-p vec1) (tramp-file-name-p vec2) + (string-equal (tramp-file-name-method vec1) + (tramp-file-name-method vec2)) + (string-equal (tramp-file-name-user-domain vec1) + (tramp-file-name-user-domain vec2)) + (string-equal (tramp-file-name-host-port vec1) + (tramp-file-name-host-port vec2)))) + (defun tramp-get-method-parameter (vec param) "Return the method parameter PARAM. If VEC is a vector, check first in connection properties. @@ -1143,69 +1180,6 @@ entry does not exist, return nil." (assoc param (assoc (tramp-file-name-method vec) tramp-methods)))) (when methods-entry (cadr methods-entry)))))) -(defun tramp-file-name-p (vec) - "Check, whether VEC is a Tramp object." - (and (vectorp vec) (= 5 (length vec)))) - -(defun tramp-file-name-method (vec) - "Return method component of VEC." - (and (tramp-file-name-p vec) (aref vec 0))) - -(defun tramp-file-name-user (vec) - "Return user component of VEC." - (and (tramp-file-name-p vec) (aref vec 1))) - -(defun tramp-file-name-host (vec) - "Return host component of VEC." - (and (tramp-file-name-p vec) (aref vec 2))) - -(defun tramp-file-name-localname (vec) - "Return localname component of VEC." - (and (tramp-file-name-p vec) (aref vec 3))) - -(defun tramp-file-name-hop (vec) - "Return hop component of VEC." - (and (tramp-file-name-p vec) (aref vec 4))) - -;; The user part of a Tramp file name vector can be of kind -;; "user%domain". Sometimes, we must extract these parts. -(defun tramp-file-name-real-user (vec) - "Return the user name of VEC without domain." - (save-match-data - (let ((user (tramp-file-name-user vec))) - (if (and (stringp user) - (string-match tramp-user-with-domain-regexp user)) - (match-string 1 user) - user)))) - -(defun tramp-file-name-domain (vec) - "Return the domain name of VEC." - (save-match-data - (let ((user (tramp-file-name-user vec))) - (and (stringp user) - (string-match tramp-user-with-domain-regexp user) - (match-string 2 user))))) - -;; The host part of a Tramp file name vector can be of kind -;; "host#port". Sometimes, we must extract these parts. -(defun tramp-file-name-real-host (vec) - "Return the host name of VEC without port." - (save-match-data - (let ((host (tramp-file-name-host vec))) - (if (and (stringp host) - (string-match tramp-host-with-port-regexp host)) - (match-string 1 host) - host)))) - -(defun tramp-file-name-port (vec) - "Return the port number of VEC." - (save-match-data - (let ((host (tramp-file-name-host vec))) - (or (and (stringp host) - (string-match tramp-host-with-port-regexp host) - (string-to-number (match-string 2 host))) - (tramp-get-method-parameter vec 'tramp-default-port))))) - ;; The localname can be quoted with "/:". Extract this. (defun tramp-file-name-unquote-localname (vec) "Return unquoted localname component of VEC." @@ -1299,43 +1273,67 @@ values." (user (match-string (nth 2 (tramp-file-name-structure)) name)) (host (match-string (nth 3 (tramp-file-name-structure)) name)) (localname (match-string (nth 4 (tramp-file-name-structure)) name)) - (hop (match-string (nth 5 (tramp-file-name-structure)) name))) + (hop (match-string (nth 5 (tramp-file-name-structure)) name)) + domain port) + (when user + (when (string-match tramp-user-with-domain-regexp user) + (setq domain (match-string 2 user) + user (match-string 1 user)))) + (when host + (when (string-match tramp-host-with-port-regexp host) + (setq port (match-string 2 host) + host (match-string 1 host))) (when (string-match (tramp-prefix-ipv6-regexp) host) (setq host (replace-match "" nil t host))) (when (string-match (tramp-postfix-ipv6-regexp) host) (setq host (replace-match "" nil t host)))) - (if nodefault - (vector method user host localname hop) - (vector - (tramp-find-method method user host) - (tramp-find-user method user host) - (tramp-find-host method user host) - localname hop)))))) + + (unless nodefault + (setq method (tramp-find-method method user host) + user (tramp-find-user method user host) + host (tramp-find-host method user host))) + + (apply + 'make-tramp-file-name + (append + (unless (zerop (length method)) `(:method ,method)) + (unless (zerop (length user)) `(:user ,user)) + (unless (zerop (length domain)) `(:domain ,domain)) + (unless (zerop (length host)) `(:host ,host)) + (unless (zerop (length port)) `(:port ,port)) + `(:localname ,(or localname "")) + (unless (zerop (length hop)) `(:hop ,hop)))))))) (defun tramp-buffer-name (vec) "A name for the connection buffer VEC." (let ((method (tramp-file-name-method vec)) - (user (tramp-file-name-user vec)) - (host (tramp-file-name-real-host vec))) - (if (not (zerop (length user))) - (format "*tramp/%s %s@%s*" method user host) - (format "*tramp/%s %s*" method host)))) - -(defun tramp-make-tramp-file-name (method user host localname &optional hop) + (user-domain (tramp-file-name-user-domain vec)) + (host-port (tramp-file-name-host-port vec))) + (if (not (zerop (length user-domain))) + (format "*tramp/%s %s@%s*" method user-domain host-port) + (format "*tramp/%s %s*" method host-port)))) + +(defun tramp-make-tramp-file-name + (method user domain host port localname &optional hop) "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME. -When not nil, an optional HOP is prepended." +When not nil, optional DOMAIN, PORT and HOP are used." (concat (tramp-prefix-format) hop (unless (or (zerop (length method)) (zerop (length (tramp-postfix-method-format)))) (concat method (tramp-postfix-method-format))) + user + (unless (zerop (length domain)) + (concat tramp-prefix-domain-format domain)) (unless (zerop (length user)) - (concat user tramp-postfix-user-format)) + tramp-postfix-user-format) (when host (if (string-match tramp-ipv6-regexp host) (concat (tramp-prefix-ipv6-format) host (tramp-postfix-ipv6-format)) host)) + (unless (zerop (length port)) + (concat tramp-prefix-port-format port)) (tramp-postfix-host-format) (when localname localname))) @@ -1372,7 +1370,9 @@ necessary only. This function will be used in file name completion." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) "/")) (current-buffer)))) @@ -1406,8 +1406,8 @@ version, the function does nothing." 'hack-connection-local-variables-apply `(:application tramp :protocol ,(tramp-file-name-method vec) - :user ,(tramp-file-name-user vec) - :machine ,(tramp-file-name-host vec))))) + :user ,(tramp-file-name-user-domain vec) + :machine ,(tramp-file-name-host-port vec))))) (defun tramp-set-connection-local-variables-for-buffer () "Set connection-local variables in the current buffer. @@ -1425,11 +1425,11 @@ version, the function does nothing." (defun tramp-debug-buffer-name (vec) "A name for the debug buffer for VEC." (let ((method (tramp-file-name-method vec)) - (user (tramp-file-name-user vec)) - (host (tramp-file-name-real-host vec))) - (if (not (zerop (length user))) - (format "*debug tramp/%s %s@%s*" method user host) - (format "*debug tramp/%s %s*" method host)))) + (user-domain (tramp-file-name-user-domain vec)) + (host-port (tramp-file-name-host-port vec))) + (if (not (zerop (length user-domain))) + (format "*debug tramp/%s %s@%s*" method user-domain host-port) + (format "*debug tramp/%s %s*" method host-port)))) (defconst tramp-debug-outline-regexp "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #" @@ -1576,7 +1576,7 @@ applicable)." (setq fmt-string (concat fmt-string "\n%s") arguments (append arguments (list (buffer-string))))))) ;; Do it. - (when (vectorp vec-or-proc) + (when (tramp-file-name-p vec-or-proc) (apply 'tramp-debug-message vec-or-proc (concat (format "(%d) # " level) fmt-string) @@ -1615,9 +1615,9 @@ an input event arrives. The other arguments are passed to `tramp-error'." (save-window-excursion (let* ((buf (or (and (bufferp buf) buf) (and (processp vec-or-proc) (process-buffer vec-or-proc)) - (and (vectorp vec-or-proc) + (and (tramp-file-name-p vec-or-proc) (tramp-get-connection-buffer vec-or-proc)))) - (vec (or (and (vectorp vec-or-proc) vec-or-proc) + (vec (or (and (tramp-file-name-p vec-or-proc) vec-or-proc) (and buf (with-current-buffer buf (tramp-dissect-file-name default-directory)))))) (unwind-protect @@ -1639,8 +1639,7 @@ an input event arrives. The other arguments are passed to `tramp-error'." (discard-input) (sit-for 30))) ;; Reset timestamp. It would be wrong after waiting for a while. - (when (equal (butlast (append vec nil) 2) - (car tramp-current-connection)) + (when (tramp-file-name-equal-p vec (car tramp-current-connection)) (setcdr tramp-current-connection (current-time))))))) (defmacro with-parsed-tramp-file-name (filename var &rest body) @@ -1664,7 +1663,7 @@ If VAR is nil, then we bind `v' to the structure and `method', `user', `(,(if var (intern (format "%s-%s" var elem)) elem) (,(intern (format "tramp-file-name-%s" elem)) ,(or var 'v)))) - '(method user host localname hop)))) + '(method user domain host port localname hop)))) `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename)) ,@bindings) ;; We don't know which of those vars will be used, so we bind them all, @@ -2508,15 +2507,13 @@ remote host and localname (filename on remote host)." (save-match-data (when (string-match (nth 0 structure) name) - (let ((method (and (nth 1 structure) - (match-string (nth 1 structure) name))) - (user (and (nth 2 structure) - (match-string (nth 2 structure) name))) - (host (and (nth 3 structure) - (match-string (nth 3 structure) name))) - (localname (and (nth 4 structure) - (match-string (nth 4 structure) name)))) - (vector method user host localname nil))))) + (make-tramp-file-name + :method (and (nth 1 structure) + (match-string (nth 1 structure) name)) + :user (and (nth 2 structure) + (match-string (nth 2 structure) name)) + :host (and (nth 3 structure) + (match-string (nth 3 structure) name)))))) ;; This function returns all possible method completions, adding the ;; trailing method delimiter. @@ -2862,7 +2859,9 @@ User is always nil." (tramp-make-tramp-file-name (tramp-file-name-method v) (tramp-file-name-user v) + (tramp-file-name-domain v) (tramp-file-name-host v) + (tramp-file-name-port v) (if (and (zerop (length (tramp-file-name-localname v))) (not (tramp-connectable-p file))) "" @@ -2951,7 +2950,9 @@ User is always nil." (tramp-make-tramp-file-name (tramp-file-name-method v) (tramp-file-name-user v) + (tramp-file-name-domain v) (tramp-file-name-host v) + (tramp-file-name-port v) (tramp-run-real-handler 'file-name-directory (list (or (tramp-file-name-localname v) ""))) (tramp-file-name-hop v)))) @@ -2993,11 +2994,13 @@ User is always nil." (and (or (not connected) c) (cond ((eq identification 'method) method) - ((eq identification 'user) user) - ((eq identification 'host) host) + ;; Domain and port are appended. + ((eq identification 'user) (tramp-file-name-user-domain v)) + ((eq identification 'host) (tramp-file-name-host-port v)) ((eq identification 'localname) localname) ((eq identification 'hop) hop) - (t (tramp-make-tramp-file-name method user host "" hop))))))))) + (t (tramp-make-tramp-file-name + method user domain host port "" hop))))))))) (defun tramp-handle-file-symlink-p (filename) "Like `file-symlink-p' for Tramp files." @@ -3005,7 +3008,7 @@ User is always nil." (let ((x (tramp-compat-file-attribute-type (file-attributes filename)))) (when (stringp x) (if (file-name-absolute-p x) - (tramp-make-tramp-file-name method user host x) + (tramp-make-tramp-file-name method user domain host port x) x))))) (defun tramp-handle-find-backup-file-name (filename) @@ -3020,7 +3023,8 @@ User is always nil." (if (and (stringp (cdr x)) (file-name-absolute-p (cdr x)) (not (tramp-file-name-p (cdr x)))) - (tramp-make-tramp-file-name method user host (cdr x)) + (tramp-make-tramp-file-name + method user domain host port (cdr x)) (cdr x)))) tramp-backup-directory-alist) backup-directory-alist))) @@ -3125,7 +3129,7 @@ User is always nil." ((stringp remote-copy) (file-local-copy (tramp-make-tramp-file-name - method user host remote-copy))) + method user domain host port remote-copy))) ((stringp tramp-temp-buffer-file-name) (copy-file filename tramp-temp-buffer-file-name 'ok) @@ -3170,7 +3174,8 @@ User is always nil." (delete-file local-copy)) (when (stringp remote-copy) (delete-file - (tramp-make-tramp-file-name method user host remote-copy))))) + (tramp-make-tramp-file-name + method user domain host port remote-copy))))) ;; Result. (list (expand-file-name filename) @@ -3548,7 +3553,8 @@ connection buffer." (tramp-set-connection-property (tramp-dissect-file-name (tramp-make-tramp-file-name - tramp-current-method tramp-current-user tramp-current-host "")) + tramp-current-method tramp-current-user tramp-current-domain + tramp-current-host tramp-current-port "")) "first-password-request" t) (save-restriction (with-tramp-progress-reporter @@ -3933,7 +3939,9 @@ be granted." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) (tramp-file-name-localname vec) (tramp-file-name-hop vec)) (intern suffix)))) @@ -3979,12 +3987,13 @@ be granted." ;;;###tramp-autoload (defun tramp-local-host-p (vec) "Return t if this points to the local host, nil otherwise." - ;; We cannot use `tramp-file-name-real-host'. A port is an - ;; indication for an ssh tunnel or alike. - (let ((host (tramp-file-name-host vec))) + (let ((host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec))) (and (stringp host) (string-match tramp-local-host-regexp host) + ;; A port is an indication for an ssh tunnel or alike. + (null port) ;; The method shall be applied to one of the shell file name ;; handlers. `tramp-local-host-p' is also called for "smb" and ;; alike, where it must fail. @@ -3994,7 +4003,8 @@ be granted." (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) - host + (tramp-file-name-domain vec) + host port (tramp-compat-temporary-file-directory))) ;; On some systems, chown runs only for root. (or (zerop (user-uid)) @@ -4008,7 +4018,9 @@ be granted." (let ((dir (tramp-make-tramp-file-name (tramp-file-name-method vec) (tramp-file-name-user vec) + (tramp-file-name-domain vec) (tramp-file-name-host vec) + (tramp-file-name-port vec) (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp") (tramp-file-name-hop vec)))) (or (and (file-directory-p dir) (file-writable-p dir) @@ -4124,8 +4136,9 @@ PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." (let ((default-directory (tramp-compat-temporary-file-directory)) (v (or vec - (vector tramp-current-method tramp-current-user - tramp-current-host nil nil))) + (tramp-make-tramp-file-name + tramp-current-method tramp-current-user tramp-current-domain + tramp-current-host tramp-current-port nil nil))) (destination (if (eq destination t) (current-buffer) destination)) output error result) (tramp-message @@ -4159,8 +4172,9 @@ PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." (let ((default-directory (tramp-compat-temporary-file-directory)) (v (or vec - (vector tramp-current-method tramp-current-user - tramp-current-host nil nil))) + (tramp-make-tramp-file-name + tramp-current-method tramp-current-user tramp-current-domain + tramp-current-host tramp-current-port nil nil))) (buffer (if (eq buffer t) (current-buffer) buffer)) result) (tramp-message @@ -4191,8 +4205,8 @@ Consults the auth-source package. Invokes `password-read' if available, `read-passwd' else." (let* ((case-fold-search t) (key (tramp-make-tramp-file-name - tramp-current-method tramp-current-user - tramp-current-host "")) + tramp-current-method tramp-current-user tramp-current-domain + tramp-current-host tramp-current-port "")) (pw-prompt (or prompt (with-current-buffer (process-buffer proc) @@ -4248,7 +4262,9 @@ Invokes `password-read' if available, `read-passwd' else." "Clear password cache for connection related to VEC." (let ((method (tramp-file-name-method vec)) (user (tramp-file-name-user vec)) + (domain (tramp-file-name-domain vec)) (host (tramp-file-name-host vec)) + (port (tramp-file-name-port vec)) (hop (tramp-file-name-hop vec))) (when hop ;; Clear also the passwords of the hops. @@ -4266,7 +4282,8 @@ Invokes `password-read' if available, `read-passwd' else." `(:max 1 ,(and user :user) ,user :host ,host :port ,method)) (tramp-compat-funcall 'auth-source-forget-user-or-password "password" host method)) - (password-cache-remove (tramp-make-tramp-file-name method user host "")))) + (password-cache-remove + (tramp-make-tramp-file-name method user domain host port "")))) ;; Snarfed code from time-date.el. @@ -4393,12 +4410,6 @@ Only works for Bourne-like shells." ;; . ;; (Bug#6850) ;; -;; * Use also port to distinguish connections. This is needed for -;; different hosts sitting behind a single router (distinguished by -;; different port numbers). (Tzvi Edelman) -;; Also needed for different systems serve SSH on different ports of -;; the same IP address. (Bug#27009) -;; ;; * Refactor code from different handlers. Start with ;; *-process-file. One idea is to generalize `tramp-send-command' ;; and friends, for most of the handlers this is the major commit 08f00c01d6f19a3b4465cc856c6ae55a1acdc350 Author: Stephen Berman Date: Wed May 24 13:33:27 2017 +0200 Fix and improve UI of scroll bar menu (bug#27047) In addition, since the Emacs manual writes "scroll bar", "tool bar" and "menu bar", use this convention in the Show/Hide menues and tooltips as well. * lisp/menu-bar.el (menu-bar-showhide-scroll-bar-menu): Make pressing a radio button in the menu actually show that it was pressed. Replace the two radio buttons to turn the horizontal scroll bar on and off with a single check-box toggle and add a separator between this and the vertical scroll bar radio buttons. Use conventional spelling. (menu-bar-horizontal-scroll-bar) (menu-bar-no-horizontal-scroll-bar): Remove, since now unused. (menu-bar-showhide-tool-bar-menu, menu-bar-showhide-menu) (menu-bar-mode): Use conventional spelling. diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 6befa6d234..9c7bcffbaa 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -970,54 +970,40 @@ The selected font will be the default on both the existing and future frames." (interactive) (customize-set-variable 'scroll-bar-mode nil)) -(defun menu-bar-horizontal-scroll-bar () - "Display horizontal scroll bars on each window." - (interactive) - (customize-set-variable 'horizontal-scroll-bar-mode t)) - -(defun menu-bar-no-horizontal-scroll-bar () - "Turn off horizontal scroll bars." - (interactive) - (customize-set-variable 'horizontal-scroll-bar-mode nil)) - (defvar menu-bar-showhide-scroll-bar-menu - (let ((menu (make-sparse-keymap "Scroll-bar")) - (vsb (frame-parameter nil 'vertical-scroll-bars)) - (hsb (frame-parameter nil 'horizontal-scroll-bars))) + (let ((menu (make-sparse-keymap "Scroll Bar"))) + (bindings--define-key menu [horizontal] - `(menu-item "Horizontal" - menu-bar-horizontal-scroll-bar - :help "Horizontal scroll bar" - :visible (horizontal-scroll-bars-available-p) - :button (:radio . ,hsb))) - - (bindings--define-key menu [none-horizontal] - `(menu-item "None-horizontal" - menu-bar-no-horizontal-scroll-bar - :help "Turn off horizontal scroll bars" - :visible (horizontal-scroll-bars-available-p) - :button (:radio . (not ,hsb)))) + (menu-bar-make-mm-toggle horizontal-scroll-bar-mode + "Horizontal" + "Horizontal scroll bar")) + + (bindings--define-key menu [scrollbar-separator] + menu-bar-separator) (bindings--define-key menu [right] - `(menu-item "On the Right" - menu-bar-right-scroll-bar - :help "Scroll-bar on the right side" + '(menu-item "On the Right" menu-bar-right-scroll-bar + :help "Scroll bar on the right side" :visible (display-graphic-p) - :button (:radio . (eq ,vsb 'right)))) + :button (:radio . (and scroll-bar-mode + (eq (frame-parameter + nil 'vertical-scroll-bars) + 'right))))) (bindings--define-key menu [left] - `(menu-item "On the Left" - menu-bar-left-scroll-bar - :help "Scroll-bar on the left side" + '(menu-item "On the Left" menu-bar-left-scroll-bar + :help "Scroll bar on the left side" :visible (display-graphic-p) - :button (:radio . (eq ,vsb 'left)))) + :button (:radio . (and scroll-bar-mode + (eq (frame-parameter + nil 'vertical-scroll-bars) + 'left))))) (bindings--define-key menu [none] - `(menu-item "None" - menu-bar-no-scroll-bar - :help "Turn off scroll-bar" + '(menu-item "No Vertical Scroll Bar" menu-bar-no-scroll-bar + :help "Turn off vertical scroll bar" :visible (display-graphic-p) - :button (:radio . (not ,vsb)))) + :button (:radio . (eq scroll-bar-mode nil)))) menu)) (defun menu-bar-frame-for-menubar () @@ -1057,24 +1043,24 @@ The selected font will be the default on both the existing and future frames." (when (featurep 'move-toolbar) (defvar menu-bar-showhide-tool-bar-menu - (let ((menu (make-sparse-keymap "Tool-bar"))) + (let ((menu (make-sparse-keymap "Tool Bar"))) (bindings--define-key menu [showhide-tool-bar-left] '(menu-item "On the Left" menu-bar-showhide-tool-bar-menu-customize-enable-left - :help "Tool-bar at the left side" + :help "Tool bar at the left side" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode - (eq (frame-parameter + (frame-parameter (menu-bar-frame-for-menubar) 'tool-bar-position) - 'left))))) + 'left)))) (bindings--define-key menu [showhide-tool-bar-right] '(menu-item "On the Right" menu-bar-showhide-tool-bar-menu-customize-enable-right - :help "Tool-bar at the right side" + :help "Tool bar at the right side" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode @@ -1086,7 +1072,7 @@ The selected font will be the default on both the existing and future frames." (bindings--define-key menu [showhide-tool-bar-bottom] '(menu-item "On the Bottom" menu-bar-showhide-tool-bar-menu-customize-enable-bottom - :help "Tool-bar at the bottom" + :help "Tool bar at the bottom" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode @@ -1098,7 +1084,7 @@ The selected font will be the default on both the existing and future frames." (bindings--define-key menu [showhide-tool-bar-top] '(menu-item "On the Top" menu-bar-showhide-tool-bar-menu-customize-enable-top - :help "Tool-bar at the top" + :help "Tool bar at the top" :visible (display-graphic-p) :button (:radio . (and tool-bar-mode @@ -1110,7 +1096,7 @@ The selected font will be the default on both the existing and future frames." (bindings--define-key menu [showhide-tool-bar-none] '(menu-item "None" menu-bar-showhide-tool-bar-menu-customize-disable - :help "Turn tool-bar off" + :help "Turn tool bar off" :visible (display-graphic-p) :button (:radio . (eq tool-bar-mode nil)))) menu))) @@ -1168,7 +1154,7 @@ mail status in mode line")) :visible (display-graphic-p))) (bindings--define-key menu [showhide-scroll-bar] - `(menu-item "Scroll-bar" ,menu-bar-showhide-scroll-bar-menu + `(menu-item "Scroll Bar" ,menu-bar-showhide-scroll-bar-menu :visible (display-graphic-p))) (bindings--define-key menu [showhide-tooltip-mode] @@ -1178,8 +1164,8 @@ mail status in mode line")) :button (:toggle . tooltip-mode))) (bindings--define-key menu [menu-bar-mode] - '(menu-item "Menu-bar" toggle-menu-bar-mode-from-frame - :help "Turn menu-bar on/off" + '(menu-item "Menu Bar" toggle-menu-bar-mode-from-frame + :help "Turn menu bar on/off" :button (:toggle . (menu-bar-positive-p (frame-parameter (menu-bar-frame-for-menubar) @@ -1188,12 +1174,12 @@ mail status in mode line")) (if (and (boundp 'menu-bar-showhide-tool-bar-menu) (keymapp menu-bar-showhide-tool-bar-menu)) (bindings--define-key menu [showhide-tool-bar] - `(menu-item "Tool-bar" ,menu-bar-showhide-tool-bar-menu + `(menu-item "Tool Bar" ,menu-bar-showhide-tool-bar-menu :visible (display-graphic-p))) ;; else not tool bar that can move. (bindings--define-key menu [showhide-tool-bar] - '(menu-item "Tool-bar" toggle-tool-bar-mode-from-frame - :help "Turn tool-bar on/off" + '(menu-item "Tool Bar" toggle-tool-bar-mode-from-frame + :help "Turn tool bar on/off" :visible (display-graphic-p) :button (:toggle . (menu-bar-positive-p @@ -2268,11 +2254,11 @@ created in the future." (assq-delete-all 'menu-bar-lines default-frame-alist))))) ;; Make the message appear when Emacs is idle. We can not call message - ;; directly. The minor-mode message "Menu-bar mode disabled" comes + ;; directly. The minor-mode message "Menu Bar mode disabled" comes ;; after this function returns, overwriting any message we do here. (when (and (called-interactively-p 'interactive) (not menu-bar-mode)) (run-with-idle-timer 0 nil 'message - "Menu-bar mode disabled. Use M-x menu-bar-mode to make the menu bar appear."))) + "Menu Bar mode disabled. Use M-x menu-bar-mode to make the menu bar appear."))) ;;;###autoload ;; (This does not work right unless it comes after the above definition.) commit bba9917299e3628e40462a762f2a14bb8df193f0 Author: Katsumi Yamaoka Date: Wed May 24 08:18:52 2017 +0000 Remove string-as-unibyte * lisp/gnus/canlock.el (canlock-sha1): Remove useless variable. (canlock-make-cancel-key): No need to use string-as-unibyte. diff --git a/lisp/gnus/canlock.el b/lisp/gnus/canlock.el index 9e13ced467..5157256594 100644 --- a/lisp/gnus/canlock.el +++ b/lisp/gnus/canlock.el @@ -72,8 +72,7 @@ buffer does not look like a news message." (defun canlock-sha1 (message) "Make a SHA-1 digest of MESSAGE as a unibyte string of length 20 bytes." - (let (sha1-maximum-internal-length) - (sha1 message nil nil 'binary))) + (sha1 message nil nil 'binary)) (defun canlock-make-cancel-key (message-id password) "Make a Cancel-Key header." @@ -87,10 +86,7 @@ buffer does not look like a news message." (char-to-string (logxor 92 byte))) password ""))) (base64-encode-string - (canlock-sha1 - (concat opad - (canlock-sha1 - (concat ipad (string-as-unibyte message-id)))))))) + (canlock-sha1 (concat opad (canlock-sha1 (concat ipad message-id))))))) (defun canlock-narrow-to-header () "Narrow the buffer to the head of the message." commit 61ef5c612d05d62b2190870ea7289251c3e092c6 Author: Tino Calancha Date: Wed May 24 10:54:48 2017 +0900 Fix concatenation of "^" with diff-file-junk-re This regexp contains "\\|", thus a concatenation of "^" with it just matches the beginning of line for the first alternative in diff-file-junk-re. * lisp/vc/ediff-ptch.el (ediff-map-patch-buffer): Concat "^" with diff-file-junk-re wrapped in a shy group. diff --git a/lisp/vc/ediff-ptch.el b/lisp/vc/ediff-ptch.el index 0340672da2..6c8e925d2b 100644 --- a/lisp/vc/ediff-ptch.el +++ b/lisp/vc/ediff-ptch.el @@ -229,7 +229,7 @@ program." "/dev/null"))) ;; Remove file junk (Bug#26084). (while (re-search-backward - (concat "^" diff-file-junk-re) mark1-end t) + (concat "^\\(?:" diff-file-junk-re "\\)") mark1-end t) (move-marker mark2 (match-beginning 0))) (goto-char mark2-end) (if filenames commit 2389ba2ebec4123453796dc5ebbb6452a17ddd92 Author: Glenn Morris Date: Tue May 23 20:44:52 2017 -0400 Suppress intermittent test failure on hydra * test/lisp/emacs-lisp/eieio-tests/eieio-tests.el (eieio-test-37-obsolete-name-in-constructor): Skip on hydra. diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el index db601abbd0..c34560ab58 100644 --- a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el +++ b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el @@ -893,6 +893,8 @@ Subclasses to override slot attributes.") (list newname 2)) (ert-deftest eieio-test-37-obsolete-name-in-constructor () + ;; FIXME repeated intermittent failures on hydra (bug#24503) + (skip-unless (not (getenv "NIX_STORE"))) (should (equal (eieio--testing "toto") '("toto" 2)))) (ert-deftest eieio-autoload () commit 2a7bd9dc600bab3eeed69bc6b755508868665e3d Author: Glenn Morris Date: Tue May 23 20:42:28 2017 -0400 ; Move recent test file to correct directory (my mistake) diff --git a/test/lisp/dns-mode-tests.el b/test/lisp/textmodes/dns-mode-tests.el similarity index 100% rename from test/lisp/dns-mode-tests.el rename to test/lisp/textmodes/dns-mode-tests.el commit 8f6550b38c8b467a8f26c63050bd842f4fdc0b1e Author: Peder O. Klingenberg Date: Tue May 23 20:34:08 2017 -0400 New dns-mode command for IPv6 address conversion This converts IPv6 addresses to a format suitable for reverse lookup zone files. (Bug#26820) * lisp/textmodes/dns-mode.el (dns-mode-map, dns-mode-menu): Add dns-mode-ipv6-to-nibbles. (dns-mode-ipv6-to-nibbles, dns-mode-reverse-and-expand-ipv6): New functions. * test/lisp/dns-mode-tests.el: New file. ; * etc/NEWS: Mention this. diff --git a/etc/NEWS b/etc/NEWS index 2ca91d5d79..2a7c48d811 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -850,6 +850,10 @@ This is done with the help of 'c-or-c++-mode' function which analyses contents of the buffer to determine whether it's a C or C++ source file. +--- +** New DNS mode command 'dns-mode-ipv6-to-nibbles' to convert IPv6 addresses +to a format suitable for reverse lookup zone files. + ** Flymake +++ diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el index cc8bad6337..7bdadbfe6f 100644 --- a/lisp/textmodes/dns-mode.el +++ b/lisp/textmodes/dns-mode.el @@ -147,6 +147,7 @@ manually with \\[dns-mode-soa-increment-serial]." (defvar dns-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-c\C-s" 'dns-mode-soa-increment-serial) + (define-key map "\C-c\C-e" 'dns-mode-ipv6-to-nibbles) map) "Keymap for DNS master file mode.") @@ -158,7 +159,8 @@ manually with \\[dns-mode-soa-increment-serial]." (easy-menu-define dns-mode-menu dns-mode-map "DNS Menu." '("DNS" - ["Increment SOA serial" dns-mode-soa-increment-serial t])) + ["Increment SOA serial" dns-mode-soa-increment-serial t] + ["Convert IPv6 address to nibbles" dns-mode-ipv6-to-nibbles t])) ;; Mode. @@ -254,6 +256,101 @@ This function is run from `before-save-hook'." ;; We return nil in case this is used in write-contents-functions. nil))) +;;;###autoload +(defun dns-mode-ipv6-to-nibbles (&optional negate-prefix) + "Convert an IPv6 address around or before point. +Replace the address by its ip6.arpa-representation for use in +reverse zone files, placing the original address in the kill ring. + +The address can be: a complete address (no prefix designator); +with a normal prefix designator (e.g. /48), in which case only +the required number of nibbles are output; or with a negative +prefix designator (e.g. /-112), in which case only the part of +the address *not* covered by the absolute value of the prefix +length is output, as a relative address (without \".ip6.arpa.\" at +the end). This is useful when $ORIGIN is specified in the zone file. + +Optional prefix argument NEGATE-PREFIX negates the value of the +detected prefix length. + +Examples: + +2001:db8::12 => +2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. + +2001:db8::12/32 => +8.b.d.0.1.0.0.2.ip6.arpa. + +2001:db8::12/-32 => +2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 + +::42/112 (with prefix argument) => +2.4.0.0" + (interactive "P") + (skip-syntax-backward " ") + (skip-syntax-backward "w_.") + (re-search-forward "\\([[:xdigit:]:]+\\)\\(/-?[0-9]\\{2,3\\}\\)?") + (kill-new (match-string 0)) + (let ((address (match-string 1)) + (prefix-length (match-string 2))) + (when prefix-length + (setq prefix-length (string-to-number (substring prefix-length 1))) + (if negate-prefix + (setq prefix-length (- prefix-length)))) + (replace-match + (save-match-data + (dns-mode-reverse-and-expand-ipv6 address prefix-length))))) + +(defun dns-mode-reverse-and-expand-ipv6 (address &optional prefix-length) + "Convert an IPv6 address to (parts of) an ip6.arpa nibble format. +ADDRESS is an IPv6 address in the usual colon-separated +format, without a prefix designator at the end. + +Optional PREFIX-LENGTH is a number whose absolute value is the +length in bits of the network part of the address. If nil, +return an absolute address representing the full IPv6 address. +If positive, return an absolute address representing the network +prefix indicated. If negative, return a relative address +representing the host parts of the address with respect to the +indicated network prefix. + +See `dns-mode-ipv6-to-nibbles' for examples." + (let* ((chunks (split-string address ":")) + (prefix-length-nibbles (if prefix-length + (ceiling (abs prefix-length) 4) + 32)) + (filler-chunks (- 8 (length (remove "" chunks)))) + (expanded-address + (apply #'concat + (cl-loop with filler-done = nil + for chunk in chunks + if (and (not filler-done) + (string= "" chunk)) + append (prog1 + (cl-loop repeat filler-chunks + collect "0000") + (setq filler-done t)) + else + if (not (string= "" chunk)) + collect (format "%04x" + (string-to-number chunk 16))))) + (rev-address-nibbles + (nreverse (if (and prefix-length + (cl-minusp prefix-length)) + (substring expanded-address prefix-length-nibbles) + (substring expanded-address 0 prefix-length-nibbles))))) + (with-temp-buffer + (cl-loop for char across rev-address-nibbles + do + (insert char) + (insert ".")) + (if (and prefix-length + (cl-minusp prefix-length)) + (delete-char -1) + (insert "ip6.arpa.")) + (insert " ") + (buffer-string)))) + (provide 'dns-mode) ;;; dns-mode.el ends here diff --git a/test/lisp/dns-mode-tests.el b/test/lisp/dns-mode-tests.el new file mode 100644 index 0000000000..34e86201d8 --- /dev/null +++ b/test/lisp/dns-mode-tests.el @@ -0,0 +1,58 @@ +;;; dns-mode-tests.el --- Test suite for dns-mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Free Software Foundation, Inc. + +;; Author: Peder O. Klingenberg +;; Keywords: dns zone + +;; 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 . + +;;; Code: + +(require 'ert) +(require 'dns-mode) + +;;; IPv6 reverse zones +(ert-deftest dns-mode-ipv6-conversion () + (let ((address "2001:db8::42")) + (should (equal (dns-mode-reverse-and-expand-ipv6 address) + "2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. ")) + (should (equal (dns-mode-reverse-and-expand-ipv6 address 32) + "8.b.d.0.1.0.0.2.ip6.arpa. ")) + (should (equal (dns-mode-reverse-and-expand-ipv6 address -112) + "2.4.0.0 ")))) + +(ert-deftest dns-mode-ipv6-text-replacement () + (let ((address "2001:db8::42/32")) + (with-temp-buffer + ;; Conversion with point directly after address + (insert address) + (dns-mode-ipv6-to-nibbles nil) + (should (equal (buffer-string) "8.b.d.0.1.0.0.2.ip6.arpa. ")) + ;; Kill ring contains the expected + (erase-buffer) + (yank) + (should (equal (buffer-string) address)) + ;; Point at beginning of address (and prefix arg to command) + (goto-char (point-min)) + (dns-mode-ipv6-to-nibbles t) + (should (equal (buffer-string) "2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 ")) + ;; Point separated from address by whitespace + (erase-buffer) + (insert address) + (insert " ") + (dns-mode-ipv6-to-nibbles nil) + (should (equal (buffer-string) "8.b.d.0.1.0.0.2.ip6.arpa. "))))) commit ef9f5c672a8e248dd7bd682101c03feb2e527340 Author: Noam Postavsky Date: Tue Apr 25 08:39:17 2017 -0400 Protect *Backtrace* from being killed (Bug#26650) * lisp/emacs-lisp/debug.el (debugger-mode): Call `top-level' in `kill-buffer-hook'. diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index cb77148c28..83456fc31a 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -727,6 +727,9 @@ Complete list of commands: \\{debugger-mode-map}" (setq truncate-lines t) (set-syntax-table emacs-lisp-mode-syntax-table) + (add-hook 'kill-buffer-hook + (lambda () (if (> (recursion-depth) 0) (top-level))) + nil t) (use-local-map debugger-mode-map)) (defcustom debugger-record-buffer "*Debugger-record*" commit d158629cb6d0dd7cf0227d993d59ea6faa4438c9 Author: Noam Postavsky Date: Fri Apr 21 00:00:26 2017 -0400 Give a name to lisp-mode's adaptive-fill-function (Bug#22730) * lisp/emacs-lisp/lisp-mode.el (lisp-adaptive-fill): New function. (lisp-mode-variables): Use it. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 3334471d25..1e38d44e1b 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -576,6 +576,13 @@ Lisp font lock syntactic face function." font-lock-string-face)))) font-lock-comment-face)) +(defun lisp-adaptive-fill () + "Return fill prefix found at point. +Value for `adaptive-fill-function'." + ;; Adaptive fill mode gets the fill wrong for a one-line paragraph made of + ;; a single docstring. Let's fix it here. + (if (looking-at "\\s-+\"[^\n\"]+\"\\s-*$") "")) + (defun lisp-mode-variables (&optional lisp-syntax keywords-case-insensitive elisp) "Common initialization routine for lisp modes. @@ -587,10 +594,7 @@ font-lock keywords will not be case sensitive." (set-syntax-table lisp-mode-syntax-table)) (setq-local paragraph-ignore-fill-prefix t) (setq-local fill-paragraph-function 'lisp-fill-paragraph) - ;; Adaptive fill mode gets the fill wrong for a one-line paragraph made of - ;; a single docstring. Let's fix it here. - (setq-local adaptive-fill-function - (lambda () (if (looking-at "\\s-+\"[^\n\"]+\"\\s-*$") ""))) + (setq-local adaptive-fill-function #'lisp-adaptive-fill) ;; Adaptive fill mode gets in the way of auto-fill, ;; and should make no difference for explicit fill ;; because lisp-fill-paragraph should do the job. commit bf4f69ab6d7d5b5d693c4acb91a4d8e6ce46e32d Author: Philipp Stephani Date: Tue May 23 21:23:55 2017 +0200 vc-hg.el: Silence byte compiler warning * lisp/vc/vc-hg.el (compilation-arguments): Forward-declare. diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index ef7afd3726..4be529624a 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1303,6 +1303,7 @@ REV is the revision to check out into WORKFILE." (autoload 'vc-do-async-command "vc-dispatcher") (autoload 'log-view-get-marked "log-view") (defvar compilation-directory) +(defvar compilation-arguments) ; defined in compile.el (defun vc-hg--pushpull (command prompt &optional obsolete) "Run COMMAND (a string; either push or pull) on the current Hg branch. commit cd9c7a0617b58169b5788ff30de97afdbac5e882 Author: Paul Eggert Date: Tue May 23 21:18:35 2017 +0200 Don't warn about missing brances on macOS On macOS, removing -Wmissing-braces is not enough; the warning has to be disabled explicitly. diff --git a/configure.ac b/configure.ac index 12e44d949c..6d23b5d214 100644 --- a/configure.ac +++ b/configure.ac @@ -986,6 +986,7 @@ AS_IF([test $gl_gcc_warnings = no], # More things that clang is unduly picky about. if test $emacs_cv_clang = yes; then + gl_WARN_ADD([-Wno-missing-braces]) gl_WARN_ADD([-Wno-tautological-compare]) gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) fi commit 63d0a3c63f833faad7a04fb4bf384d55ae6ae8d1 Author: Wilfred Hughes Date: Tue May 23 18:48:19 2017 +0100 Don't treat ' as a string delimiter in RPM spec files ' is commonly used as an apostrophe in the prose sections of spec files, which was erroneously highlighted as strings. See for example http://kmymoney2.sourceforge.net/phb/rpm-example.html * lisp/progmodes/sh-script.el (sh-mode-syntax-table): Treat ' as punctuation in RPM spec files. diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index db965c5a58..35b555e687 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -492,7 +492,10 @@ name symbol." This is buffer-local in every such buffer.") (defvar sh-mode-syntax-table-input - '((sh . nil)) + `((sh . nil) + ;; Treat ' as punctuation rather than a string delimiter, as RPM + ;; files often contain prose with apostrophes. + (rpm . (,sh-mode-syntax-table ?\' "."))) "Syntax-table used in Shell-Script mode. See `sh-feature'.") (defvar sh-mode-map commit 9b0662d3698692f99384cfc8d1bd0b41b0625e09 Author: Stefan Monnier Date: Tue May 23 09:23:54 2017 -0400 * lisp/emacs-lisp/cl-indent.el: Don't require CL. Use lexical-binding. (common-lisp-indent-function-1): Remove unused var `last-point`. (lisp-indent-error-function): Move defvar before first use. diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el index 33ecf3f454..9941d17359 100644 --- a/lisp/emacs-lisp/cl-indent.el +++ b/lisp/emacs-lisp/cl-indent.el @@ -1,4 +1,4 @@ -;;; cl-indent.el --- enhanced lisp-indent mode +;;; cl-indent.el --- Enhanced lisp-indent mode -*- lexical-binding:t -*- ;; Copyright (C) 1987, 2000-2017 Free Software Foundation, Inc. @@ -35,7 +35,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(eval-when-compile (require 'cl-lib)) (defgroup lisp-indent nil "Indentation in Lisp." @@ -187,13 +187,13 @@ the standard lisp indent package." (when (and (eq lisp-indent-backquote-substitution-mode 'corrected)) (save-excursion (goto-char (elt state 1)) - (incf loop-indentation - (cond ((eq (char-before) ?,) -1) - ((and (eq (char-before) ?@) - (progn (backward-char) - (eq (char-before) ?,))) - -2) - (t 0))))) + (cl-incf loop-indentation + (cond ((eq (char-before) ?,) -1) + ((and (eq (char-before) ?@) + (progn (backward-char) + (eq (char-before) ?,))) + -2) + (t 0))))) (goto-char indent-point) (beginning-of-line) @@ -315,7 +315,6 @@ instead." ;; If non-nil, this is an indentation to use ;; if nothing else specifies it more firmly. tentative-calculated - (last-point indent-point) ;; the position of the open-paren of the innermost containing list (containing-form-start (elt state 1)) ;; the column of the above @@ -410,9 +409,9 @@ instead." ;; ",(...)" or ",@(...)" (when (eq lisp-indent-backquote-substitution-mode 'corrected) - (incf sexp-column -1) + (cl-incf sexp-column -1) (when (eq (char-after (1- containing-sexp)) ?\@) - (incf sexp-column -1))) + (cl-incf sexp-column -1))) (cond (lisp-indent-backquote-substitution-mode (setf tentative-calculated normal-indent) (setq depth lisp-indent-maximum-backtracking) @@ -465,7 +464,6 @@ instead." function method path state indent-point sexp-column normal-indent))))) (goto-char containing-sexp) - (setq last-point containing-sexp) (unless calculated (condition-case () (progn (backward-up-list 1) @@ -474,6 +472,9 @@ instead." (or calculated tentative-calculated)))) +;; Dynamically bound in common-lisp-indent-call-method. +(defvar lisp-indent-error-function) + (defun common-lisp-indent-call-method (function method path state indent-point sexp-column normal-indent) (let ((lisp-indent-error-function function)) @@ -484,9 +485,6 @@ instead." (lisp-indent-259 method path state indent-point sexp-column normal-indent)))) -;; Dynamically bound in common-lisp-indent-call-method. -(defvar lisp-indent-error-function) - (defun lisp-indent-report-bad-format (m) (error "%s has a badly-formed %s property: %s" ;; Love those free variable references!! @@ -717,7 +715,7 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\ (forward-sexp 2) (skip-chars-forward " \t\n") (while (looking-at "\\sw\\|\\s_") - (incf nqual) + (cl-incf nqual) (forward-sexp) (skip-chars-forward " \t\n")) (> nqual 0))) @@ -726,7 +724,7 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\ path state indent-point sexp-column normal-indent)) -(defun lisp-indent-function-lambda-hack (path state indent-point +(defun lisp-indent-function-lambda-hack (path _state _indent-point sexp-column normal-indent) ;; indent (function (lambda () )) kludgily. (if (or (cdr path) ; wtf? commit 2eee73e7bf5a6bee18272248876eb8820d3db568 Author: Stefan Monnier Date: Tue May 23 09:18:26 2017 -0400 * lisp/international/rfc1843.el: Don't require CL. Use lexical-binding. diff --git a/lisp/international/rfc1843.el b/lisp/international/rfc1843.el index c1343274c9..9b91854714 100644 --- a/lisp/international/rfc1843.el +++ b/lisp/international/rfc1843.el @@ -1,4 +1,4 @@ -;;; rfc1843.el --- HZ (rfc1843) decoding +;;; rfc1843.el --- HZ (rfc1843) decoding -*- lexical-binding:t -*- ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. @@ -27,7 +27,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(eval-when-compile (require 'cl-lib)) (defvar rfc1843-word-regexp "~\\({\\([\041-\167][\041-\176]\\| \\)+\\)\\(~}\\|$\\)") @@ -115,15 +115,15 @@ ftp://ftp.math.psu.edu/pub/simpson/chinese/hzp/hzp.doc" "Decode HZ WORD and return it." (let ((i -1) (s (substring word 0)) v) (if (or (not firstc) (eq firstc ?{)) - (while (< (incf i) (length s)) + (while (< (cl-incf i) (length s)) (if (eq (setq v (aref s i)) ? ) nil (aset s i (+ 128 v)))) - (while (< (incf i) (length s)) + (while (< (cl-incf i) (length s)) (if (eq (setq v (aref s i)) ? ) nil (setq v (+ (* 94 v) (aref s (1+ i)) -3135)) (aset s i (+ (/ v 157) (if (eq firstc ?<) 201 161))) (setq v (% v 157)) - (aset s (incf i) (+ v (if (< v 63) 64 98)))))) + (aset s (cl-incf i) (+ v (if (< v 63) 64 98)))))) s)) (provide 'rfc1843) commit f037e98fe90aea530ab03437afbfb2337fc676a3 Author: Stefan Monnier Date: Tue May 23 09:12:06 2017 -0400 * lisp/international/utf7.el: Don't require CL. Use lexical-binding. diff --git a/lisp/international/utf7.el b/lisp/international/utf7.el index 82dad3da6e..f245d7eb69 100644 --- a/lisp/international/utf7.el +++ b/lisp/international/utf7.el @@ -1,4 +1,4 @@ -;;; utf7.el --- UTF-7 encoding/decoding for Emacs -*-coding: utf-8;-*- +;;; utf7.el --- UTF-7 encoding/decoding for Emacs -*- lexical-binding:t -*- ;; Copyright (C) 1999-2017 Free Software Foundation, Inc. @@ -64,7 +64,6 @@ ;;; Code: (require 'base64) -(eval-when-compile (require 'cl)) (require 'mm-util) (defconst utf7-direct-encoding-chars " -%'-*,-[]-}" @@ -140,8 +139,7 @@ Use IMAP modification if FOR-IMAP is non-nil." (defun utf7-decode-internal (&optional for-imap) "Decode UTF-7 text in (temporary) buffer. Use IMAP modification if FOR-IMAP is non-nil." - (let ((start (point-min)) - (end (point-max))) + (let ((start (point-min))) (goto-char start) (let* ((esc-pattern (concat "^" (char-to-string (if for-imap ?& ?+)))) (base64-chars (concat "A-Za-z0-9+" commit a8d0a91841121a7bdae668a5f29c1ba84739e14f Author: Stefan Monnier Date: Tue May 23 09:09:28 2017 -0400 * lisp/net/shr.el: Use cl-lib instead of cl. diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 6b62a05227..2a6b3960c4 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -30,7 +30,7 @@ ;;; Code: -(eval-when-compile (require 'cl)) +(eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'url)) ;For url-filename's setf handler. (require 'browse-url) (eval-when-compile (require 'subr-x)) @@ -1790,14 +1790,14 @@ The preference is a float determined from `shr-prefer-media-type'." (elems (or (dom-attr dom 'shr-suggested-widths) (shr-make-table dom suggested-widths nil 'shr-suggested-widths))) - (sketch (loop for line in elems - collect (mapcar #'car line))) - (natural (loop for line in elems - collect (mapcar #'cdr line))) + (sketch (cl-loop for line in elems + collect (mapcar #'car line))) + (natural (cl-loop for line in elems + collect (mapcar #'cdr line))) (sketch-widths (shr-table-widths sketch natural suggested-widths))) ;; This probably won't work very well. - (when (> (+ (loop for width across sketch-widths - summing (1+ width)) + (when (> (+ (cl-loop for width across sketch-widths + summing (1+ width)) shr-indentation shr-table-separator-pixel-width) (frame-width)) (setq truncate-lines t)) @@ -2315,13 +2315,14 @@ flags that control whether to collect or render objects." (defun shr-dom-max-natural-width (dom max) (if (eq (dom-tag dom) 'table) (max max (or - (loop for line in (dom-attr dom 'shr-suggested-widths) - maximize (+ - shr-table-separator-length - (loop for elem in line - summing - (+ (cdr elem) - (* 2 shr-table-separator-length))))) + (cl-loop + for line in (dom-attr dom 'shr-suggested-widths) + maximize (+ + shr-table-separator-length + (cl-loop for elem in line + summing + (+ (cdr elem) + (* 2 shr-table-separator-length))))) 0)) (dolist (child (dom-children dom)) (unless (stringp child) commit 91b114354d32b5eacdfab4996cae0f3b9b4cc628 Author: Stefan Monnier Date: Tue May 23 08:39:20 2017 -0400 * test/src/fns-tests.el, test/src/data-tests.el: Don't use `cl` * test/src/data-tests.el (binding-test-manual, binding-test-setq-default) (binding-test-makunbound, data-tests-varalias-watchers) (data-tests-local-variable-watchers): Silence compiler warnings. diff --git a/test/src/data-tests.el b/test/src/data-tests.el index 67d00a7f93..8caafc11c2 100644 --- a/test/src/data-tests.el +++ b/test/src/data-tests.el @@ -22,7 +22,6 @@ ;;; Code: (require 'cl-lib) -(eval-when-compile (require 'cl)) (ert-deftest data-tests-= () (should-error (=)) @@ -141,9 +140,9 @@ 43)))) (defun mock-bool-vector-count-consecutive (a b i) - (loop for i from i below (length a) - while (eq (aref a i) b) - sum 1)) + (cl-loop for i from i below (length a) + while (eq (aref a i) b) + sum 1)) (defun test-bool-vector-bv-from-hex-string (desc) (let (bv nchars nibbles) @@ -157,7 +156,7 @@ (dolist (n (nreverse nibbles)) (dotimes (_ 4) (aset bv i (> (logand 1 n) 0)) - (incf i) + (cl-incf i) (setf n (lsh n -1))))) bv)) @@ -182,9 +181,9 @@ hexadecimal digits describing the bool vector. We exhaustively test all counts at all possible positions in the vector by comparing the subr with a much slower lisp implementation." (let ((bv (test-bool-vector-bv-from-hex-string desc))) - (loop + (cl-loop for lf in '(nil t) - do (loop + do (cl-loop for pos from 0 upto (length bv) for cnt = (mock-bool-vector-count-consecutive bv lf pos) for rcnt = (bool-vector-count-consecutive bv lf pos) @@ -217,36 +216,36 @@ comparing the subr with a much slower lisp implementation." (defun test-bool-vector-apply-mock-op (mock a b c) "Compute (slowly) the correct result of a bool-vector set operation." (let (changed nv) - (assert (eql (length b) (length c))) + (cl-assert (eql (length b) (length c))) (if a (setf nv a) (setf a (make-bool-vector (length b) nil)) (setf changed t)) - (loop for i below (length b) - for mockr = (funcall mock - (if (aref b i) 1 0) - (if (aref c i) 1 0)) - for r = (not (= 0 mockr)) - do (progn - (unless (eq (aref a i) r) - (setf changed t)) - (setf (aref a i) r))) + (cl-loop for i below (length b) + for mockr = (funcall mock + (if (aref b i) 1 0) + (if (aref c i) 1 0)) + for r = (not (= 0 mockr)) + do (progn + (unless (eq (aref a i) r) + (setf changed t)) + (setf (aref a i) r))) (if changed a))) (defun test-bool-vector-binop (mock real) "Test a binary set operation." - (loop for s1 in bool-vector-test-vectors - for bv1 = (test-bool-vector-bv-from-hex-string s1) - for vecs2 = (cl-remove-if-not - (lambda (x) (eql (length x) (length s1))) - bool-vector-test-vectors) - do (loop for s2 in vecs2 - for bv2 = (test-bool-vector-bv-from-hex-string s2) - for mock-result = (test-bool-vector-apply-mock-op - mock nil bv1 bv2) - for real-result = (funcall real bv1 bv2) - do (progn - (should (equal mock-result real-result)))))) + (cl-loop for s1 in bool-vector-test-vectors + for bv1 = (test-bool-vector-bv-from-hex-string s1) + for vecs2 = (cl-remove-if-not + (lambda (x) (eql (length x) (length s1))) + bool-vector-test-vectors) + do (cl-loop for s2 in vecs2 + for bv2 = (test-bool-vector-bv-from-hex-string s2) + for mock-result = (test-bool-vector-apply-mock-op + mock nil bv1 bv2) + for real-result = (funcall real bv1 bv2) + do (progn + (should (equal mock-result real-result)))))) (ert-deftest bool-vector-intersection-op () (test-bool-vector-binop @@ -300,8 +299,7 @@ comparing the subr with a much slower lisp implementation." (ert-deftest binding-test-manual () "A test case from the elisp manual." - (save-excursion - (set-buffer binding-test-buffer-A) + (with-current-buffer binding-test-buffer-A (let ((binding-test-some-local 'something-else)) (should (eq binding-test-some-local 'something-else)) (set-buffer binding-test-buffer-B) @@ -312,8 +310,7 @@ comparing the subr with a much slower lisp implementation." (ert-deftest binding-test-setq-default () "Test that a setq-default has no effect when there is a local binding." - (save-excursion - (set-buffer binding-test-buffer-B) + (with-current-buffer binding-test-buffer-B ;; This variable is not local in this buffer. (let ((binding-test-some-local 'something-else)) (setq-default binding-test-some-local 'new-default)) @@ -321,8 +318,7 @@ comparing the subr with a much slower lisp implementation." (ert-deftest binding-test-makunbound () "Tests of makunbound, from the manual." - (save-excursion - (set-buffer binding-test-buffer-B) + (with-current-buffer binding-test-buffer-B (should (boundp 'binding-test-some-local)) (let ((binding-test-some-local 'outer)) (let ((binding-test-some-local 'inner)) @@ -406,12 +402,14 @@ comparing the subr with a much slower lisp implementation." (should (null watch-data)))) ;; Watch var0, then alias it. (add-variable-watcher 'data-tests-var0 collect-watch-data) + (defvar data-tests-var0-alias) (defvaralias 'data-tests-var0-alias 'data-tests-var0) (setq data-tests-var0 1) (should-have-watch-data '(data-tests-var0 1 set nil)) (setq data-tests-var0-alias 2) (should-have-watch-data '(data-tests-var0 2 set nil)) ;; Alias var1, then watch var1-alias. + (defvar data-tests-var1-alias) (defvaralias 'data-tests-var1-alias 'data-tests-var1) (add-variable-watcher 'data-tests-var1-alias collect-watch-data) (setq data-tests-var1 1) @@ -419,6 +417,7 @@ comparing the subr with a much slower lisp implementation." (setq data-tests-var1-alias 2) (should-have-watch-data '(data-tests-var1 2 set nil)) ;; Alias var2, then watch it. + (defvar data-tests-var2-alias) (defvaralias 'data-tests-var2-alias 'data-tests-var2) (add-variable-watcher 'data-tests-var2 collect-watch-data) (setq data-tests-var2 1) @@ -437,7 +436,8 @@ comparing the subr with a much slower lisp implementation." (should (null watch-data))))) (ert-deftest data-tests-local-variable-watchers () - (defvar-local data-tests-lvar 0) + (with-no-warnings + (defvar-local data-tests-lvar 0)) (let* ((buf1 (current-buffer)) (buf2 nil) (watch-data nil) diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index a1b48a643e..2e463455f0 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -22,7 +22,6 @@ ;;; Code: (require 'cl-lib) -(eval-when-compile (require 'cl)) (ert-deftest fns-tests-reverse () (should-error (reverse)) commit ea19dd64e28a05e3b8d10f1683862bdfad43b1a8 Author: Stefan Monnier Date: Tue May 23 08:16:59 2017 -0400 * lisp/vc/vc-hg.el (compilation-directory): Silence byte-compiler. diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index fff25ed64b..ef7afd3726 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1302,6 +1302,7 @@ REV is the revision to check out into WORKFILE." (autoload 'vc-do-async-command "vc-dispatcher") (autoload 'log-view-get-marked "log-view") +(defvar compilation-directory) (defun vc-hg--pushpull (command prompt &optional obsolete) "Run COMMAND (a string; either push or pull) on the current Hg branch. commit 4a485410ce74cafd4e9c344e31f7575464a16113 Author: Alan Third Date: Tue May 23 02:42:20 2017 -0700 Fix GNUstep build * src/nsterm.h [NS_IMPL_GNUSTEP]: Add typedefs for Cocoa-only types. (NSWindowStyleMaskUtilityWindow): #define to NSUtilityWindowMask in GNUstep and old versions of macOS. * src/nsfns.m (ns-set-mouse-absolute-pixel-position): Function only works in cocoa, not GNUstep. diff --git a/src/nsfns.m b/src/nsfns.m index 00310c051f..3833ee75ac 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -3046,6 +3046,9 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are \(0, 0) of the selected frame's display. */) (Lisp_Object x, Lisp_Object y) { +#ifdef NS_IMPL_COCOA + /* GNUstep doesn't support CGWarpMouseCursorPosition, so none of + this will work. */ struct frame *f = SELECTED_FRAME (); EmacsView *view = FRAME_NS_VIEW (f); NSScreen *screen = [[view window] screen]; @@ -3072,6 +3075,7 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are CGPoint mouse_pos = CGPointMake(mouse_x, mouse_y); CGWarpMouseCursorPosition (mouse_pos); +#endif /* NS_IMPL_COCOA */ return Qnil; } diff --git a/src/nsterm.h b/src/nsterm.h index 5da949e1fb..443a40ed6f 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -62,6 +62,13 @@ typedef CGFloat EmacsCGFloat; typedef float EmacsCGFloat; #endif +/* FIXME: It looks as though instancetype will be supported in GNUstep + at some point, but I'm not sure what version. */ +#ifdef NS_IMPL_GNUSTEP +typedef id instancetype; +typedef int NSWindowStyleMask; +#endif + /* ========================================================================== Trace support @@ -1290,6 +1297,7 @@ extern char gnustep_base_version[]; /* version tracking */ #define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask #define NSWindowStyleMaskResizable NSResizableWindowMask #define NSWindowStyleMaskTitled NSTitledWindowMask +#define NSWindowStyleMaskUtilityWindow NSUtilityWindowMask #define NSAlertStyleCritical NSCriticalAlertStyle #define NSControlSizeRegular NSRegularControlSize #endif commit 107e60f49db71f1869848f0f0ce5ea7dd057366c Author: Michael Albinus Date: Tue May 23 09:25:03 2017 +0200 Add test for Bug#27009 in tramp-tests.el * lisp/net/tramp-sh.el (tramp-compute-multi-hops): Check `tramp-file-name-real-host' for being a local host. * lisp/net/tramp.el (tramp-postfix-host-regexp): Fix docstring. * test/lisp/net/tramp-tests.el (tramp-test-temporary-file-directory): Declare default host for mock method. (tramp-test29-environment-variables-and-port-numbers): New test. diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 9b001a90e7..999de8e850 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -4546,7 +4546,7 @@ Goes through the list `tramp-inline-compress-commands'." ;; host name. (let* ((v (car target-alist)) (method (tramp-file-name-method v)) - (host (tramp-file-name-host v))) + (host (tramp-file-name-real-host v))) (unless (or ;; There are multi-hops. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 5b1e478db0..70abb89194 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -837,7 +837,7 @@ Used in `tramp-make-tramp-file-name'." (defun tramp-postfix-host-regexp () "Regexp matching delimiter between host names and localnames. -nDerived from `tramp-postfix-host-format'." +Derived from `tramp-postfix-host-format'." (regexp-quote (tramp-postfix-host-format))) (defconst tramp-localname-regexp ".*$" @@ -4396,6 +4396,8 @@ Only works for Bourne-like shells." ;; * Use also port to distinguish connections. This is needed for ;; different hosts sitting behind a single router (distinguished by ;; different port numbers). (Tzvi Edelman) +;; Also needed for different systems serve SSH on different ports of +;; the same IP address. (Bug#27009) ;; ;; * Refactor code from different handlers. Start with ;; *-process-file. One idea is to generalize `tramp-send-command' diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 49c32dbaaf..0106807a9a 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -67,6 +67,9 @@ (tramp-remote-shell "/bin/sh") (tramp-remote-shell-args ("-c")) (tramp-connection-timeout 10))) + (add-to-list + 'tramp-default-host-alist + `("\\`mock\\'" nil ,(system-name))) (format "/mock::%s" temporary-file-directory))) "Temporary directory for Tramp tests.") @@ -2920,6 +2923,42 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (regexp-quote envvar) (funcall this-shell-command-to-string "set"))))))))) +;; This test is inspired by Bug#27009. +(ert-deftest tramp-test29-environment-variables-and-port-numbers () + "Check that two connections with separate ports are different." + ;; Mark as failed until bug has been fixed. + :expected-result :failed + (skip-unless (tramp--test-enabled)) + ;; We test it only for the mock-up connection; otherwise there might + ;; be problems with the used ports. + (skip-unless + (and + (eq tramp-syntax 'default) + (string-equal + "mock" (file-remote-p tramp-test-temporary-file-directory 'method)))) + + ;; We force a reconnect, in order to have a clean environment. + (dolist (dir + `(,tramp-test-temporary-file-directory + "/mock:localhost#11111:" "/mock:localhost#22222:")) + (tramp-cleanup-connection + (tramp-dissect-file-name dir) 'keep-debug 'keep-password)) + + (dolist (port '(11111 22222)) + (let* ((default-directory + (format "/mock:localhost#%d:%s" port temporary-file-directory)) + (shell-file-name "/bin/sh") + (envvar (concat "VAR_" (upcase (md5 (current-time-string))))) + ;; We cannot use `process-environment', because this would + ;; be applied in `process-file'. + (tramp-remote-process-environment + (cons + (format "%s=%d" envvar port) tramp-remote-process-environment))) + (should + (string-equal + (number-to-string port) + (shell-command-to-string (format "echo -n $%s" envvar))))))) + ;; The functions were introduced in Emacs 26.1. (ert-deftest tramp-test30-explicit-shell-file-name () "Check that connection-local `explicit-shell-file-name' is set." @@ -3766,6 +3805,8 @@ Since it unloads Tramp, it shall be the last test to run." ;; * Fix `tramp-test05-expand-file-name-relative' in `expand-file-name'. ;; * Fix `tramp-test06-directory-file-name' for `ftp'. ;; * Fix `tramp-test27-start-file-process' on MS Windows (`process-send-eof'?). +;; * Fix Bug#27009. Set expected error of +;; `tramp-test29-environment-variables-and-port-numbers'. ;; * Fix Bug#16928. Set expected error of `tramp-test36-asynchronous-requests'. ;; * Fix `tramp-test38-unload' (Not all symbols are unbound). Set ;; expected error. commit ad2f52a14312b1b33f235103189b033b7ed87ddd Author: Glenn Morris Date: Mon May 22 19:08:10 2017 -0400 ; * lisp/net/tls.el (tls-program): Tweak :version. ; To be reset if no 25.3 happens. diff --git a/lisp/net/tls.el b/lisp/net/tls.el index a31a1a033f..11aae635aa 100644 --- a/lisp/net/tls.el +++ b/lisp/net/tls.el @@ -106,7 +106,7 @@ successful negotiation." (repeat :inline t :tag "Other" (string))) (list :tag "List of commands" (repeat :tag "Command" (string)))) - :version "26.1" ; remove s_client + :version "25.3" ; remove s_client :group 'tls) (defcustom tls-process-connection-type nil commit bc78276e81956b3caa8a5eb7ef26959fa4c84b7b Author: Stefan Monnier Date: Mon May 22 16:53:18 2017 -0400 * lisp/mail/rfc2047.el (rfc2047-decode-encoded-words): Set `words` to nil. diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el index bb8bc01dce..e2af86b324 100644 --- a/lisp/mail/rfc2047.el +++ b/lisp/mail/rfc2047.el @@ -952,6 +952,7 @@ ENCODED-WORD)." (push (cons cs text) rest)) ;; Don't decode encoded-word. (push (cons nil (nth 3 word)) rest))) + (setq words nil) (while rest ;; FIXME: This looks O(N²). Can we make it more efficient ;; with something like mapconcat? commit 62046ed3e9b1e95340eb980058b8f7aadae2447a Author: Sam Steingold Date: Mon May 22 15:48:21 2017 -0400 Fix "g" in hg&git push&pull buffers lisp/vc/vc-git.el (vc-git--pushpull): Set locally `compilation-directory' and `compilation-arguments'. lisp/vc/vc-hg.el (vc-hg--pushpull): Likewise. diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index f70bbddbe7..a4ce76ec37 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -888,7 +888,15 @@ If PROMPT is non-nil, prompt for the Git command to run." (vc-compilation-mode 'git) (setq-local compile-command (concat git-program " " command " " - (if args (mapconcat 'identity args " ") ""))))) + (if args (mapconcat 'identity args " ") ""))) + (setq-local compilation-directory root) + ;; Either set `compilation-buffer-name-function' locally to nil + ;; or use `compilation-arguments' to set `name-function'. + ;; See `compilation-buffer-name'. + (setq-local compilation-arguments + (list compile-command nil + (lambda (_name-of-mode) buffer) + nil)))) (vc-set-async-update buffer))) (defun vc-git-pull (prompt) diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index 37ea928a9c..fff25ed64b 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1344,7 +1344,15 @@ commands, which only operated on marked files." (vc-compilation-mode 'hg) (setq-local compile-command (concat hg-program " " command " " - (if args (mapconcat 'identity args " ") ""))))) + (if args (mapconcat 'identity args " ") ""))) + (setq-local compilation-directory root) + ;; Either set `compilation-buffer-name-function' locally to nil + ;; or use `compilation-arguments' to set `name-function'. + ;; See `compilation-buffer-name'. + (setq-local compilation-arguments + (list compile-command nil + (lambda (_name-of-mode) buffer) + nil)))) (vc-set-async-update buffer))))) (defun vc-hg-pull (prompt) commit bf96464e2f731c9b7a9f9589b2de001a03ed3f2f Author: Eli Zaretskii Date: Mon May 22 21:15:17 2017 +0300 Fix current-line hscrolling in buffers with header-line * src/xdisp.c (display_line): When testing the glyph row's vertical position against the cursor position, account for header line, if any. (Bug#27014) diff --git a/src/xdisp.c b/src/xdisp.c index 0588061738..ddb26b8def 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -20671,7 +20671,9 @@ display_line (struct it *it, int cursor_vpos) ptrdiff_t min_pos = ZV + 1, max_pos = 0; ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; bool pending_handle_line_prefix = false; - bool hscroll_this_line = (cursor_vpos >= 0 && it->vpos == cursor_vpos + int header_line = WINDOW_WANTS_HEADER_LINE_P (it->w); + bool hscroll_this_line = (cursor_vpos >= 0 + && it->vpos == cursor_vpos - header_line && hscrolling_current_line_p (it->w)); int first_visible_x = it->first_visible_x; int last_visible_x = it->last_visible_x; commit e7b9a6fc4adc584b1c89a8e7502734d063fab2cd Author: Stefan Monnier Date: Sun May 21 23:18:58 2017 -0400 * lisp/mail/rfc2047.el: Use cl-lib & lexical-binding, silence warning (rfc2047-decode-encoded-words): Use dolist. (rfc2047-decode-string): Avoid string-to-multibyte. (rfc2047-pad-base64): Use pcase. diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el index d276e2117f..bb8bc01dce 100644 --- a/lisp/mail/rfc2047.el +++ b/lisp/mail/rfc2047.el @@ -1,4 +1,4 @@ -;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages +;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages -*- lexical-binding:t -*- ;; Copyright (C) 1998-2017 Free Software Foundation, Inc. @@ -26,8 +26,7 @@ ;;; Code: -(eval-when-compile - (require 'cl)) +(eval-when-compile (require 'cl-lib)) (defvar message-posting-charset) (require 'mm-util) @@ -155,7 +154,7 @@ This is either `base64' or `quoted-printable'." (goto-char (point-min)) (skip-chars-forward "\x20-\x7f\r\n\t" limit) (while (< (point) limit) - (incf n8bit) + (cl-incf n8bit) (forward-char 1) (skip-chars-forward "\x20-\x7f\r\n\t" limit)) (if (or (< (* 6 n8bit) (- limit (point-min))) @@ -931,11 +930,10 @@ only be used for decoding, not for encoding." "Decode successive encoded-words in WORDS and return a decoded string. Each element of WORDS looks like (CHARSET ENCODING ENCODED-TEXT ENCODED-WORD)." - (let (word charset cs encoding text rest) - (while words - (setq word (pop words)) + (let (cs text rest) + (dolist (word words) (if (and (setq cs (rfc2047-charset-to-coding-system - (setq charset (car word)) t)) + (car word) t)) (condition-case code (cond ((char-equal ?B (nth 1 word)) (setq text (base64-decode-string @@ -955,6 +953,8 @@ ENCODED-WORD)." ;; Don't decode encoded-word. (push (cons nil (nth 3 word)) rest))) (while rest + ;; FIXME: This looks O(N²). Can we make it more efficient + ;; with something like mapconcat? (setq words (concat (or (and (setq cs (caar rest)) (condition-case code @@ -1140,7 +1140,9 @@ other than `\"' and `\\' in quoted strings." ;; string is purely ASCII string (decode-coding-string string mail-parse-charset)) - (string-to-multibyte string)))) + (if (multibyte-string-p string) + string + (decode-coding-string string 'us-ascii))))) (defun rfc2047-decode-address-string (string) "Decode MIME-encoded STRING and return the result. @@ -1157,7 +1159,7 @@ strings are stripped." string (when (string-match "=+$" string) (setq string (substring string 0 (match-beginning 0)))) - (case (mod (length string) 4) + (pcase (mod (length string) 4) (0 string) (1 string) ;; Error, don't pad it. (2 (concat string "==")) commit 08848e33baf16d3137b171205f51839d8fcf7d06 Author: Dima Kogan Date: Tue Mar 24 12:53:08 2015 -0700 Make ff-find-other-file symmetric for C++ (Bug#20192) `cc-other-file-alist' has a mapping of file extensions to switch between headers and sources, but the mappings weren't completely symmetric. In particular .cpp would map to .hh, but .hh would NOT map to .cpp. * lisp/find-file.el (cc-other-file-alist): Map ".hh" and ".h" to all C++ extensions to make them symmetric with the C++ extensions that map to them. This lets repeated invocations of `ff-find-other-file' toggle between all pairs of sources/headers. diff --git a/lisp/find-file.el b/lisp/find-file.el index e02bea06fc..d3691694d1 100644 --- a/lisp/find-file.el +++ b/lisp/find-file.el @@ -242,11 +242,11 @@ the preceding slash. The star represents all the subdirectories except (defcustom cc-other-file-alist '(("\\.cc\\'" (".hh" ".h")) - ("\\.hh\\'" (".cc" ".C")) + ("\\.hh\\'" (".cc" ".C" ".CC" ".cxx" ".cpp" ".c++")) ("\\.c\\'" (".h")) ("\\.m\\'" (".h")) - ("\\.h\\'" (".c" ".cc" ".C" ".CC" ".cxx" ".cpp" ".m")) + ("\\.h\\'" (".c" ".cc" ".C" ".CC" ".cxx" ".cpp" ".c++" ".m")) ("\\.C\\'" (".H" ".hh" ".h")) ("\\.H\\'" (".C" ".CC")) commit 32f80eb678c4dc6335063cc39975bbce2766829a Author: Philipp Stephani Date: Sat May 20 17:49:06 2017 +0200 Fix definition of whitespace in JSON See https://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00115.html. * lisp/json.el (json-skip-whitespace): Fix definition. * test/lisp/json-tests.el (test-json-skip-whitespace): Adapt unit test. diff --git a/lisp/json.el b/lisp/json.el index 5f403a411b..3def94ce04 100644 --- a/lisp/json.el +++ b/lisp/json.el @@ -206,7 +206,11 @@ Unlike `reverse', this keeps the property-value pairs intact." (defun json-skip-whitespace () "Skip past the whitespace at point." - (skip-chars-forward "\t\r\n\f\b ")) + ;; See + ;; https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf + ;; or https://tools.ietf.org/html/rfc7159#section-2 for the + ;; definition of whitespace in JSON. + (skip-chars-forward "\t\r\n ")) diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el index 38672de066..c6bd295d66 100644 --- a/test/lisp/json-tests.el +++ b/test/lisp/json-tests.el @@ -89,7 +89,10 @@ Point is moved to beginning of the buffer." (ert-deftest test-json-skip-whitespace () (json-tests--with-temp-buffer "\t\r\n\f\b { \"a\": 1 }" (json-skip-whitespace) - (should (equal (char-after (point)) ?{)))) + (should (equal (char-after) ?\f))) + (json-tests--with-temp-buffer "\t\r\n\t { \"a\": 1 }" + (json-skip-whitespace) + (should (equal (char-after) ?{)))) ;;; Paths commit 140aefc341da9cc865971d393071be029ff8b3c5 Author: Paul Eggert Date: Sun May 21 13:41:43 2017 -0700 ; Spelling fix diff --git a/lisp/bindings.el b/lisp/bindings.el index 0b4c3bda80..0e6ffc275e 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -376,7 +376,7 @@ displayed in `mode-line-position', a component of the default (-3 "%o")) (const :tag "\"%p\": Percentage offset of top of window" (-3 "%p")) - (const :tag "\"%P\": Precentage offset of bottom of window" + (const :tag "\"%P\": Percentage offset of bottom of window" (-3 "%P")) (const :tag "\"%q\": Offsets of both top and bottom of window" (6 "%q"))) commit b69f6a779a65f1f3e0963d6fd280ae95970f5325 Author: Philipp Stephani Date: Sun May 21 22:33:50 2017 +0200 Improve module function terminology Module functions were previously called "function environments" when the functions created by module_make_functions were lambdas. Now we can adapt the terminology and rename "function environments" to "module functions" everywhere. This also removes the name clash between "function environments" and "module environments." * src/emacs-module.c (module_make_function): Adapt comment to reality; stop using "function environment" terminology. (funcall_module): Stop using "function environment" terminology. diff --git a/src/emacs-module.c b/src/emacs-module.c index 5ab6913595..33c5fbd484 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -342,12 +342,8 @@ module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value) value_to_lisp (value)); } -/* A module function is lambda function that calls - `internal--module-call', passing the function pointer of the module - function along with the module emacs_env pointer as arguments. - - (function (lambda (&rest arglist) - (internal--module-call envobj arglist))) */ +/* A module function is a pseudovector of subtype type + PVEC_MODULE_FUNCTION; see lisp.h for the definition. */ static emacs_value module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, @@ -363,24 +359,24 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, : min_arity <= max_arity && max_arity <= MOST_POSITIVE_FIXNUM))) xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity)); - struct Lisp_Module_Function *envptr = allocate_module_function (); - envptr->min_arity = min_arity; - envptr->max_arity = max_arity; - envptr->subr = subr; - envptr->data = data; + struct Lisp_Module_Function *function = allocate_module_function (); + function->min_arity = min_arity; + function->max_arity = max_arity; + function->subr = subr; + function->data = data; if (documentation) { AUTO_STRING (unibyte_doc, documentation); - envptr->documentation = + function->documentation = code_convert_string_norecord (unibyte_doc, Qutf_8, false); } - Lisp_Object envobj; - XSET_MODULE_FUNCTION (envobj, envptr); - eassert (MODULE_FUNCTIONP (envobj)); + Lisp_Object result; + XSET_MODULE_FUNCTION (result, function); + eassert (MODULE_FUNCTIONP (result)); - return lisp_to_value (envobj); + return lisp_to_value (result); } static emacs_value @@ -644,13 +640,13 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0, } Lisp_Object -funcall_module (const struct Lisp_Module_Function *const envptr, +funcall_module (const struct Lisp_Module_Function *const function, ptrdiff_t nargs, Lisp_Object *arglist) { - eassume (0 <= envptr->min_arity); - if (! (envptr->min_arity <= nargs - && (envptr->max_arity < 0 || nargs <= envptr->max_arity))) - xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr), + eassume (0 <= function->min_arity); + if (! (function->min_arity <= nargs + && (function->max_arity < 0 || nargs <= function->max_arity))) + xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (function), make_number (nargs)); emacs_env pub; @@ -668,7 +664,7 @@ funcall_module (const struct Lisp_Module_Function *const envptr, args[i] = lisp_to_value (arglist[i]); } - emacs_value ret = envptr->subr (&pub, nargs, args, envptr->data); + emacs_value ret = function->subr (&pub, nargs, args, function->data); SAFE_FREE (); eassert (&priv == pub.private_members); diff --git a/src/lisp.h b/src/lisp.h index f423a66d5a..7290386b25 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3901,9 +3901,9 @@ extern void unexec_free (void *); typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t, emacs_value [], void *); -/* Function environments. */ +/* Module function. */ -/* A function environment is an auxiliary structure used by +/* A function environment is an auxiliary structure returned by `module_make_function' to store information about a module function. It is stored in a pseudovector. Its members correspond to the arguments given to `module_make_function'. */ commit 6f1f88224c62dfb7b311dc1a57db267d118cae5c Author: Philipp Stephani Date: Sat May 20 16:57:58 2017 +0200 Avoid uninitialized read * src/nsterm.m (ns_read_socket): Don't read uninitialized variable 'nevents'. diff --git a/src/nsterm.m b/src/nsterm.m index c8320130a8..e69aa43dd3 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4261,6 +4261,8 @@ in certain situations (rapid incoming events). q_event_ptr = NULL; unblock_input (); } + else + return -1; return nevents; } commit fa389f5b54aedab0b4cc5f8fb6f558e55b27d55d Author: Philipp Stephani Date: Sat May 20 16:56:38 2017 +0200 Fix call of registerServicesMenuSendTypes * src/nsterm.m (initFrameFromEmacs:): nil is not allowed for returnTypes; pass an empty array instead. diff --git a/src/nsterm.m b/src/nsterm.m index 6e138b7eb6..c8320130a8 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -7022,7 +7022,7 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f [self allocateGState]; #endif [NSApp registerServicesMenuSendTypes: ns_send_types - returnTypes: nil]; + returnTypes: [NSArray array]]; /* macOS Sierra automatically enables tabbed windows. We can't allow this to be enabled until it's available on a Free system. commit 6dd94bcc6b44ee06917d76d638120eca2cf59377 Author: Philipp Stephani Date: Sat May 20 16:55:00 2017 +0200 Clean up code around 'ns-list-services' * src/nsfns.m (Fns_list_services): Remove unreachable code. In this branch NS_IMPL_COCOA cannot be defined. (interpret_services_menu): Define only if called to avoid compiler warnings about unused static functions. diff --git a/src/nsfns.m b/src/nsfns.m index a815ce656c..00310c051f 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -175,6 +175,7 @@ Updated by Christian Limpach (chris@nice.ch) #endif } +#ifndef NS_IMPL_COCOA static Lisp_Object interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old) /* -------------------------------------------------------------------------- @@ -223,7 +224,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side } return old; } - +#endif /* ========================================================================== @@ -2107,9 +2108,6 @@ and GNUstep implementations ("distributor-specific release #else Lisp_Object ret = Qnil; NSMenu *svcs; -#ifdef NS_IMPL_COCOA - id delegate; -#endif check_window_system (NULL); svcs = [[NSMenu alloc] initWithTitle: @"Services"]; @@ -2117,33 +2115,7 @@ and GNUstep implementations ("distributor-specific release [NSApp registerServicesMenuSendTypes: ns_send_types returnTypes: ns_return_types]; -/* On Tiger, services menu updating was made lazier (waits for user to - actually click on the menu), so we have to force things along: */ -#ifdef NS_IMPL_COCOA - delegate = [svcs delegate]; - if (delegate != nil) - { - if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)]) - [delegate menuNeedsUpdate: svcs]; - if ([delegate respondsToSelector: - @selector (menu:updateItem:atIndex:shouldCancel:)]) - { - int i, len = [delegate numberOfItemsInMenu: svcs]; - for (i =0; i Date: Sat May 20 16:52:10 2017 +0200 Remove unused automatic variables * nsterm.m (ns_read_socket): * macfont.m (macfont_open): Remove unused automatic variables. diff --git a/src/macfont.m b/src/macfont.m index be8153390d..4d310e47ae 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -2536,8 +2536,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no int size; CTFontRef macfont; CTFontSymbolicTraits sym_traits; - char name[256]; - int len, i, total_width; + int i, total_width; CGGlyph glyph; CGFloat ascent, descent, leading; diff --git a/src/nsterm.m b/src/nsterm.m index 8b0c3cf249..6e138b7eb6 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4247,7 +4247,6 @@ in certain situations (rapid incoming events). } else { - ptrdiff_t specpdl_count = SPECPDL_INDEX (); /* Run and wait for events. We must always send one NX_APPDEFINED event to ourself, otherwise [NXApp run] will never exit. */ send_appdefined = YES; commit 74d43044d3ad0f875034a1ee5510507ff59a70c8 Author: Philipp Stephani Date: Sat May 20 16:50:40 2017 +0200 Nextstep: Replace deprecated enumerators * src/nsmenu.m (initWithContentRect:styleMask:backing:defer:): Replace deprecated enumerator. diff --git a/src/nsmenu.m b/src/nsmenu.m index 8dcbe194d5..37a1a62d6d 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1517,7 +1517,7 @@ - (instancetype)initWithContentRect: (NSRect)contentRect styleMask: (NSWindowSty [img autorelease]; [imgView autorelease]; - aStyle = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSUtilityWindowMask; + aStyle = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskUtilityWindow; flag = YES; rows = 0; cols = 1; commit 762be778fcb55bc56286d3abc1bd92a3331423d9 Author: Philipp Stephani Date: Sat May 20 16:49:16 2017 +0200 Nextstep: remove some deprecated method calls * src/nsterm.m (mouseDown:): * src/nsmenu.m (runMenuAt:forFrame:keymaps:): Remove call to deprecated method. The return value is always nil. * src/macfont.m (mac_font_shape_1): Replace call to deprecated method. diff --git a/src/macfont.m b/src/macfont.m index dccb4e6fd0..be8153390d 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -410,8 +410,9 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, /* For now we assume the direction is not changed within the string. */ [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1)) - glyphs:NULL characterIndexes:NULL - glyphInscriptions:NULL elasticBits:NULL + glyphs:NULL + properties:NULL + characterIndexes:NULL bidiLevels:&bidiLevel]; if (bidiLevel & 1) permutation = xmalloc (sizeof (NSUInteger) * used); diff --git a/src/nsmenu.m b/src/nsmenu.m index 5e863bb17d..8dcbe194d5 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -750,7 +750,7 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f modifierFlags: 0 timestamp: [e timestamp] windowNumber: [[view window] windowNumber] - context: [e context] + context: nil eventNumber: 0/*[e eventNumber] */ clickCount: 1 pressure: 0]; diff --git a/src/nsterm.m b/src/nsterm.m index 785147ae8d..8b0c3cf249 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -8602,7 +8602,7 @@ - (void)mouseDown: (NSEvent *)e modifierFlags: [e modifierFlags] timestamp: [e timestamp] windowNumber: [e windowNumber] - context: [e context] + context: nil eventNumber: [e eventNumber] clickCount: [e clickCount] pressure: [e pressure]]; commit f04e3d6e204142469f0e0df9309e246b12920b35 Author: Philipp Stephani Date: Sat May 20 16:47:11 2017 +0200 Remove trailing semicolons in method definitions These semicolons are ignored and cause compiler warnings. * src/nsimage.m (setPixelAtX:Y:toRed:green:blue:alpha:): * src/nsterm.m (init, updateFrameSize:): (setFrame:): Remove trailing semicolon. diff --git a/src/nsimage.m b/src/nsimage.m index 1c82fa780a..fb2322afc3 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -386,7 +386,7 @@ - (unsigned long) getPixelAtX: (int)x Y: (int)y - (void) setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r green: (unsigned char)g blue: (unsigned char)b - alpha:(unsigned char)a; + alpha:(unsigned char)a { if (bmRep == nil) return; diff --git a/src/nsterm.m b/src/nsterm.m index 50ce9398fb..785147ae8d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1317,7 +1317,7 @@ - (void)remove; @implementation EmacsBell -- (id)init; +- (id)init { NSTRACE ("[EmacsBell init]"); if ((self = [super init])) @@ -6529,7 +6529,7 @@ - (BOOL)windowShouldClose: (id)sender return NO; } -- (void) updateFrameSize: (BOOL) delay; +- (void) updateFrameSize: (BOOL) delay { NSWindow *window = [self window]; NSRect wr = [window frame]; @@ -6847,7 +6847,7 @@ - (void)windowWillMiniaturize: sender } -- (void)setFrame:(NSRect)frameRect; +- (void)setFrame:(NSRect)frameRect { NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]", NSTRACE_ARG_RECT (frameRect)); commit add0b69445f65fe1792fe3ab5f8a8d35b997f728 Author: Philipp Stephani Date: Sat May 20 16:44:40 2017 +0200 Remove calls to deprecated setUsesScreenFonts * src/macfont.m (mac_screen_font_get_metrics): Don't call setUsesScreenFonts. (mac_font_shape_1): Remove screen_font_p parameter. (mac_screen_font_shape): Remove screen_font_p argument. diff --git a/src/macfont.m b/src/macfont.m index b859eb4378..dccb4e6fd0 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -284,7 +284,6 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, [textStorage setFont:nsFont]; [textContainer setLineFragmentPadding:0]; - [layoutManager setUsesScreenFonts:YES]; [layoutManager addTextContainer:textContainer]; [textContainer release]; @@ -318,8 +317,7 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, static CFIndex mac_font_shape_1 (NSFont *font, NSString *string, - struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len, - BOOL screen_font_p) + struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) { NSUInteger i; CFIndex result = 0; @@ -339,7 +337,6 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, initWithString:@" "] autorelease])]; [textStorage setFont:font]; [textContainer setLineFragmentPadding:0]; - [layoutManager setUsesScreenFonts:screen_font_p]; [layoutManager addTextContainer:textContainer]; [textContainer release]; @@ -587,7 +584,7 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, { return mac_font_shape_1 ([(NSFont *)font printerFont], (NSString *) string, - glyph_layouts, glyph_len, YES); + glyph_layouts, glyph_len); } static CGColorRef commit cc6db8b6aa5ddda9a8ca51d836096be991836d07 Author: Philipp Stephani Date: Sat May 20 16:42:33 2017 +0200 Make a function static that isn't used outside this file * src/kqueue.c (kqueue_directory_listing): Make static. diff --git a/src/kqueue.c b/src/kqueue.c index 8e6b1e149f..a8eb4cb797 100644 --- a/src/kqueue.c +++ b/src/kqueue.c @@ -42,7 +42,7 @@ static Lisp_Object watch_list; /* Generate a list from the directory_files_internal output. Items are (INODE FILE-NAME LAST-MOD LAST-STATUS-MOD SIZE). */ -Lisp_Object +static Lisp_Object kqueue_directory_listing (Lisp_Object directory_files) { Lisp_Object dl, result = Qnil; commit 0446a5a040f7a0142b33cb70946fcde54914b2ce Author: Philipp Stephani Date: Sat May 20 16:39:53 2017 +0200 Use NSCharacterCollection instead of CTCharacterCollection This should not cause behavior changes, but fixes a compiler warning due to implicit conversions between the enums. * src/macfont.m (macfont_cache, macfont_lookup_cache) (macfont_get_glyph_for_cid, macfont_get_uvs_table) (macfont_variation_glyphs): Use NSCharacterCollection. diff --git a/src/macfont.m b/src/macfont.m index f356842db1..b859eb4378 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -206,7 +206,7 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, #if !USE_CT_GLYPH_INFO static CGGlyph -mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, +mac_font_get_glyph_for_cid (CTFontRef font, NSCharacterCollection collection, CGFontIndex cid) { CGGlyph result = kCGFontIndexInvalid; @@ -1321,8 +1321,8 @@ equal to the number of rows that are invalid as BMP (i.e., from /* Character collection specifying the destination of the mapping provided by `table' above. If `table' is obtained from the UVS subtable in the font cmap table, then the value of this member - should be kCTCharacterCollectionIdentityMapping. */ - CTCharacterCollection collection; + should be NSIdentityMappingCharacterCollection. */ + NSCharacterCollection collection; } uvs; }; @@ -1333,8 +1333,8 @@ equal to the number of rows that are invalid as BMP (i.e., from static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef); static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char); static CGGlyph macfont_get_glyph_for_cid (struct font *font, - CTCharacterCollection, CGFontIndex); -static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *); + NSCharacterCollection, CGFontIndex); +static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *); static struct macfont_cache * macfont_lookup_cache (CFStringRef key) @@ -1582,7 +1582,7 @@ static CGGlyph macfont_get_glyph_for_cid (struct font *font, } static CGGlyph -macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection, +macfont_get_glyph_for_cid (struct font *font, NSCharacterCollection collection, CGFontIndex cid) { struct macfont_info *macfont_info = (struct macfont_info *) font; @@ -1593,7 +1593,7 @@ static CGGlyph macfont_get_glyph_for_cid (struct font *font, } static CFDataRef -macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection) +macfont_get_uvs_table (struct font *font, NSCharacterCollection *collection) { struct macfont_info *macfont_info = (struct macfont_info *) font; CTFontRef macfont = macfont_info->macfont; @@ -1603,12 +1603,12 @@ static CGGlyph macfont_get_glyph_for_cid (struct font *font, if (cache->uvs.table == NULL) { CFDataRef uvs_table = mac_font_copy_uvs_table (macfont); - CTCharacterCollection uvs_collection = - kCTCharacterCollectionIdentityMapping; + NSCharacterCollection uvs_collection = + NSIdentityMappingCharacterCollection; if (uvs_table == NULL && mac_font_get_glyph_for_cid (macfont, - kCTCharacterCollectionAdobeJapan1, + NSAdobeJapan1CharacterCollection, 6480) != kCGFontIndexInvalid) { /* If the glyph for U+4E55 is accessible via its CID 6480, @@ -1625,7 +1625,7 @@ static CGGlyph macfont_get_glyph_for_cid (struct font *font, if (mac_uvs_table_adobe_japan1) { uvs_table = CFRetain (mac_uvs_table_adobe_japan1); - uvs_collection = kCTCharacterCollectionAdobeJapan1; + uvs_collection = NSAdobeJapan1CharacterCollection; } } if (uvs_table == NULL) @@ -3348,7 +3348,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no macfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) { CFDataRef uvs_table; - CTCharacterCollection uvs_collection; + NSCharacterCollection uvs_collection; int i, n = 0; block_input (); @@ -3368,7 +3368,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no { CGGlyph glyph = glyphs[i]; - if (uvs_collection != kCTCharacterCollectionIdentityMapping + if (uvs_collection != NSIdentityMappingCharacterCollection && glyph != kCGFontIndexInvalid) glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph); if (glyph == kCGFontIndexInvalid) commit d79a4ea632733ac5a0b004728fde737c8952c441 Author: Philipp Stephani Date: Sat May 20 16:38:22 2017 +0200 Remove unused function print_regions diff --git a/src/unexmacosx.c b/src/unexmacosx.c index 97dcb435d3..3b1efa3ca3 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c @@ -346,31 +346,6 @@ print_region_list (void) print_region (r->address, r->size, r->protection, r->max_protection); } -static void -print_regions (void) -{ - task_t target_task = mach_task_self (); - vm_address_t address = (vm_address_t) 0; - vm_size_t size; - struct vm_region_basic_info info; - mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; - mach_port_t object_name; - - printf (" address size prot maxp\n"); - - while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO, - (vm_region_info_t) &info, &info_count, &object_name) - == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT) - { - print_region (address, size, info.protection, info.max_protection); - - if (object_name != MACH_PORT_NULL) - mach_port_deallocate (target_task, object_name); - - address += size; - } -} - /* Build the list of regions that need to be dumped. Regions with addresses above VM_DATA_TOP are omitted. Adjacent regions with identical protection are merged. Note that non-writable regions commit cf68bb4aed0c3c65f1b71cb13c506f4f706744cc Author: Philipp Stephani Date: Sat May 20 16:37:42 2017 +0200 Declare Nextstep unexec functions in lisp.h This removes compiler warnings about missing prototypes on macOS. diff --git a/src/emacs.c b/src/emacs.c index 3aa914f22f..4477f5bc01 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -137,10 +137,6 @@ static bool might_dump; #endif -#if defined DARWIN_OS && !defined CANNOT_DUMP -extern void unexec_init_emacs_zone (void); -#endif - /* If true, Emacs should not attempt to use a window-specific code, but instead should use the virtual terminal under which it was started. */ bool inhibit_window_system; diff --git a/src/lisp.h b/src/lisp.h index ec8a8b1c09..f423a66d5a 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3887,6 +3887,14 @@ extern void get_backtrace (Lisp_Object array); Lisp_Object backtrace_top_function (void); extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); +/* Defined in unexmacosx.c. */ +#if defined DARWIN_OS && !defined CANNOT_DUMP +extern void unexec_init_emacs_zone (void); +extern void *unexec_malloc (size_t); +extern void *unexec_realloc (void *, size_t); +extern void unexec_free (void *); +#endif + #include "emacs-module.h" /* Function prototype for the module Lisp functions. */ commit 84b28ec759ed3d294c2f49353942ae76e0c75532 Author: Philipp Stephani Date: Sat May 20 16:36:24 2017 +0200 Nextstep: Use instancetype explicit return type This removes compiler warnings on macOS and improves type safety. * nsterm.m (initFrameFromEmacs:): (menuDown:): (toolbarClicked:): (toggleToolbar:): (setMiniwindowImage:): (initFrame:window:): (condemn, reprieve, setPosition:portion:whole:): (repeatScroll:): * nsmenu.m (initWithTitle:): (initWithTitle:frame:): (initForView:withIdentifier:): (init, initWithContentRect:styleMask:backing:defer:): (initFromContents:isQuestion:): * nsimage.m (allocInitFromFile:): (initFromXBM:width:height:fg:bg:): (setXBMColor:): (initForXPMWithDepth:width:height:): Use instancetype as return type instead of implicit id. diff --git a/src/nsimage.m b/src/nsimage.m index e87da77ccf..1c82fa780a 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -152,7 +152,7 @@ Updated by Christian Limpach (chris@nice.ch) @implementation EmacsImage -+ allocInitFromFile: (Lisp_Object)file ++ (instancetype)allocInitFromFile: (Lisp_Object)file { NSImageRep *imgRep; Lisp_Object found; @@ -197,7 +197,7 @@ - (void)dealloc /* Create image from monochrome bitmap. If both FG and BG are 0 (black), set the background to white and make it transparent. */ -- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h +- (instancetype)initFromXBM: (unsigned char *)bits width: (int)w height: (int)h fg: (unsigned long)fg bg: (unsigned long)bg { unsigned char *planes[5]; @@ -269,7 +269,7 @@ - (void)dealloc } /* Set color for a bitmap image. */ -- setXBMColor: (NSColor *)color +- (instancetype)setXBMColor: (NSColor *)color { NSSize s = [self size]; unsigned char *planes[5]; @@ -309,7 +309,7 @@ - (void)dealloc } -- initForXPMWithDepth: (int)depth width: (int)width height: (int)height +- (instancetype)initForXPMWithDepth: (int)depth width: (int)width height: (int)height { NSSize s = {width, height}; int i; diff --git a/src/nsmenu.m b/src/nsmenu.m index 8dc6ea1d34..5e863bb17d 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -493,7 +493,7 @@ @implementation EmacsMenu /* override designated initializer */ -- initWithTitle: (NSString *)title +- (instancetype)initWithTitle: (NSString *)title { frame = 0; if ((self = [super initWithTitle: title])) @@ -503,7 +503,7 @@ @implementation EmacsMenu /* used for top-level */ -- initWithTitle: (NSString *)title frame: (struct frame *)f +- (instancetype)initWithTitle: (NSString *)title frame: (struct frame *)f { [self initWithTitle: title]; frame = f; @@ -1146,7 +1146,7 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f @implementation EmacsToolbar -- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier +- (instancetype)initForView: (EmacsView *)view withIdentifier: (NSString *)identifier { NSTRACE ("[EmacsToolbar initForView: withIdentifier:]"); @@ -1302,7 +1302,7 @@ - (void)setVisible:(BOOL)shown display. */ @implementation EmacsTooltip -- init +- (instancetype)init { NSColor *col = [NSColor colorWithCalibratedRed: 1.0 green: 1.0 blue: 0.792 alpha: 0.95]; @@ -1493,7 +1493,7 @@ @implementation EmacsDialogPanel #define TEXTHEIGHT 20.0 #define MINCELLWIDTH 90.0 -- initWithContentRect: (NSRect)contentRect styleMask: (NSUInteger)aStyle +- (instancetype)initWithContentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)aStyle backing: (NSBackingStoreType)backingType defer: (BOOL)flag { NSSize spacing = {SPACER, SPACER}; @@ -1697,7 +1697,7 @@ - (void)clicked: sender } -- initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ +- (instancetype)initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ { Lisp_Object head; [super init]; diff --git a/src/nsterm.h b/src/nsterm.h index ac339bf479..5da949e1fb 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -444,16 +444,16 @@ char const * nstrace_fullscreen_type_name (int); } /* AppKit-side interface */ -- menuDown: (id)sender; -- toolbarClicked: (id)item; -- toggleToolbar: (id)sender; +- (instancetype)menuDown: (id)sender; +- (instancetype)toolbarClicked: (id)item; +- (instancetype)toggleToolbar: (id)sender; - (void)keyDown: (NSEvent *)theEvent; - (void)mouseDown: (NSEvent *)theEvent; - (void)mouseUp: (NSEvent *)theEvent; -- setMiniwindowImage: (BOOL)setMini; +- (instancetype)setMiniwindowImage: (BOOL)setMini; /* Emacs-side interface */ -- initFrameFromEmacs: (struct frame *) f; +- (instancetype) initFrameFromEmacs: (struct frame *) f; - (void) createToolbar: (struct frame *)f; - (void) setRows: (int) r andColumns: (int) c; - (void) setWindowClosing: (BOOL)closing; @@ -513,7 +513,7 @@ char const * nstrace_fullscreen_type_name (int); unsigned long keyEquivModMask; } -- initWithTitle: (NSString *)title frame: (struct frame *)f; +- (instancetype)initWithTitle: (NSString *)title frame: (struct frame *)f; - (void)setFrame: (struct frame *)f; - (void)menuNeedsUpdate: (NSMenu *)menu; /* (delegate method) */ - (NSString *)parseKeyEquiv: (const char *)key; @@ -547,7 +547,7 @@ char const * nstrace_fullscreen_type_name (int); NSArray *prevIdentifiers; unsigned long enablement, prevEnablement; } -- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier; +- (instancetype) initForView: (EmacsView *)view withIdentifier: (NSString *)identifier; - (void) clearActive; - (void) clearAll; - (BOOL) changed; @@ -582,7 +582,7 @@ char const * nstrace_fullscreen_type_name (int); Lisp_Object dialog_return; Lisp_Object *button_values; } -- initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; +- (instancetype)initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; - (void)process_dialog: (Lisp_Object)list; - (void)addButton: (char *)str value: (int)tag row: (int)row; - (void)addString: (char *)str row: (int)row; @@ -601,7 +601,7 @@ char const * nstrace_fullscreen_type_name (int); NSTextField *textField; NSTimer *timer; } -- init; +- (instancetype) init; - (void) setText: (char *)text; - (void) showAtX: (int)x Y: (int)y for: (int)seconds; - (void) hide; @@ -649,12 +649,12 @@ char const * nstrace_fullscreen_type_name (int); NSColor *stippleMask; unsigned long xbm_fg; } -+ allocInitFromFile: (Lisp_Object)file; ++ (instancetype)allocInitFromFile: (Lisp_Object)file; - (void)dealloc; -- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h +- (instancetype)initFromXBM: (unsigned char *)bits width: (int)w height: (int)h fg: (unsigned long)fg bg: (unsigned long)bg; -- setXBMColor: (NSColor *)color; -- initForXPMWithDepth: (int)depth width: (int)width height: (int)height; +- (instancetype)setXBMColor: (NSColor *)color; +- (instancetype)initForXPMWithDepth: (int)depth width: (int)width height: (int)height; - (void)setPixmapData; - (unsigned long)getPixelAtX: (int)x Y: (int)y; - (void)setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r @@ -693,16 +693,16 @@ char const * nstrace_fullscreen_type_name (int); int em_whole; } -- initFrame: (NSRect )r window: (Lisp_Object)win; +- (instancetype) initFrame: (NSRect )r window: (Lisp_Object)win; - (void)setFrame: (NSRect)r; -- setPosition: (int) position portion: (int) portion whole: (int) whole; +- (instancetype) setPosition: (int) position portion: (int) portion whole: (int) whole; - (int) checkSamePosition: (int)position portion: (int)portion whole: (int)whole; - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e; -- repeatScroll: (NSTimer *)sender; -- condemn; -- reprieve; +- (instancetype)repeatScroll: (NSTimer *)sender; +- (instancetype)condemn; +- (instancetype)reprieve; - (bool)judge; + (CGFloat)scrollerWidth; @end @@ -725,7 +725,7 @@ char const * nstrace_fullscreen_type_name (int); unsigned long maxChar, maxGlyph; long i, len; } -- initWithCapacity: (unsigned long) c; +- (instancetype)initWithCapacity: (unsigned long) c; - (void) setString: (NSString *)str font: (NSFont *)font; @end #endif /* NS_IMPL_COCOA */ diff --git a/src/nsterm.m b/src/nsterm.m index a7ab73b63e..50ce9398fb 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -6896,7 +6896,7 @@ This avoids an extra clear and redraw (flicker) at frame creation. */ } -- initFrameFromEmacs: (struct frame *)f +- (instancetype) initFrameFromEmacs: (struct frame *)f { NSRect r, wr; Lisp_Object tem; @@ -7626,7 +7626,7 @@ - (void)mouseExited: (NSEvent *)theEvent } -- menuDown: sender +- (instancetype)menuDown: sender { NSTRACE ("[EmacsView menuDown:]"); if (context_menu_value == -1) @@ -7651,7 +7651,7 @@ - (EmacsToolbar *)toolbar /* this gets called on toolbar button click */ -- toolbarClicked: (id)item +- (instancetype)toolbarClicked: (id)item { NSEvent *theEvent; int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS; @@ -7677,7 +7677,7 @@ - (EmacsToolbar *)toolbar } -- toggleToolbar: (id)sender +- (instancetype)toggleToolbar: (id)sender { NSTRACE ("[EmacsView toggleToolbar:]"); @@ -7905,7 +7905,7 @@ - (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types (gives a miniaturized version of the window); currently we use the latter for frames whose active buffer doesn't correspond to any file (e.g., '*scratch*') */ -- setMiniwindowImage: (BOOL) setMini +- (instancetype)setMiniwindowImage: (BOOL) setMini { id image = [[self window] miniwindowImage]; NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini); @@ -8257,7 +8257,7 @@ + (CGFloat) scrollerWidth return r; } -- initFrame: (NSRect )r window: (Lisp_Object)nwin +- (instancetype)initFrame: (NSRect )r window: (Lisp_Object)nwin { NSTRACE ("[EmacsScroller initFrame: window:]"); @@ -8341,7 +8341,7 @@ - (void)dealloc } -- condemn +- (instancetype)condemn { NSTRACE ("[EmacsScroller condemn]"); condemned =YES; @@ -8349,7 +8349,7 @@ - (void)dealloc } -- reprieve +- (instancetype)reprieve { NSTRACE ("[EmacsScroller reprieve]"); condemned =NO; @@ -8404,7 +8404,7 @@ - (int) checkSamePosition: (int) position portion: (int) portion } -- setPosition: (int)position portion: (int)portion whole: (int)whole +- (instancetype)setPosition: (int)position portion: (int)portion whole: (int)whole { NSTRACE ("[EmacsScroller setPosition:portion:whole:]"); @@ -8483,7 +8483,7 @@ - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e /* called manually thru timer to implement repeated button action w/hold-down */ -- repeatScroll: (NSTimer *)scrollEntry +- (instancetype)repeatScroll: (NSTimer *)scrollEntry { NSEvent *e = [[self window] currentEvent]; NSPoint p = [[self window] mouseLocationOutsideOfEventStream]; commit 08212929ba7052883bd506be320dfaaae5b68970 Author: Tino Calancha Date: Sun May 21 22:20:19 2017 +0900 * lisp/emacs-lisp/package.el (package-delete): Delete readme file as well. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 551f440a8f..cb8e2d60d6 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2128,10 +2128,15 @@ If NOSAVE is non-nil, the package is not removed from (t (add-hook 'post-command-hook #'package-menu--post-refresh) (delete-directory dir t t) - ;; Remove NAME-VERSION.signed file. - (let ((signed-file (concat dir ".signed"))) - (if (file-exists-p signed-file) - (delete-file signed-file))) + ;; Remove NAME-VERSION.signed and NAME-readme.txt files. + (dolist (suffix '(".signed" "readme.txt")) + (let* ((version (package-version-join (package-desc-version pkg-desc))) + (file (concat (if (string= suffix ".signed") + dir + (substring dir 0 (- (length version)))) + suffix))) + (when (file-exists-p file) + (delete-file file)))) ;; Update package-alist. (let ((pkgs (assq name package-alist))) (delete pkg-desc pkgs) commit b0b02ca7f3e06d0f092df6f81babd1277bf93b0f Author: Alan Mackenzie Date: Sun May 21 10:16:09 2017 +0000 Enhance mode-line percentage offset facility, with "%o" and "%q" "%o" will display the percentage "travel" of the window through the buffer. "%q" will display a combination of the percentage offsets of the top and bottom of the window. The new user option mode-line-percent-position will facilitate selecting a setting for this part of the mode line. * lisp/bindings.el (mode-line-percent-position): New customizable user option. (mode-line-position): Use mode-line-percent-position in place of "%p", etc. * src/xdisp.c (decode_mode_spec): Add handlers for "%o" and "%q". * doc/lispref/modes.texi (Mode Line Variables): Document mode-line-percent-position. (%-Constructs): Document %o and %q. * etc/NEWS: Add an entry for these new facilities. diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index eb72fcfd36..0e476b47a3 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -1972,6 +1972,14 @@ displays the buffer percentage and, optionally, the buffer size, the line number and the column number. @end defvar +@defopt mode-line-percent-position +This option is used in @code{mode-line-position}. Its value specifies +both the buffer percentage to display (one of @code{nil}, @code{"%o"}, +@code{"%p"}, @code{"%P"} or @code{"%q"}, @pxref{%-Constructs}) and a +width to space-fill or truncate to. You are recommended to set this +option with the @code{customize-variable} facility. +@end defopt + @defvar vc-mode The variable @code{vc-mode}, buffer-local in each buffer, records whether the buffer's visited file is maintained with version control, @@ -2147,6 +2155,12 @@ of the buffer. @samp{Narrow} when narrowing is in effect; nothing otherwise (see @code{narrow-to-region} in @ref{Narrowing}). +@item %o +The degree of @dfn{travel} of the window through (the visible portion +of) the buffer, i.e. the size of the text above the top of the window +expressed as a percentage of all the text outside the window, or +@samp{Top}, @samp{Bottom} or @samp{All}. + @item %p The percentage of the buffer text above the @strong{top} of window, or @samp{Top}, @samp{Bottom} or @samp{All}. Note that the default mode @@ -2158,6 +2172,10 @@ the window (which includes the text visible in the window, as well as the text above the top), plus @samp{Top} if the top of the buffer is visible on screen; or @samp{Bottom} or @samp{All}. +@item %q +The percentages of text above both the @strong{top} and the +@strong{bottom} of the window, separated by @samp{-}, or @samp{All}. + @item %s The status of the subprocess belonging to the current buffer, obtained with @code{process-status}. @xref{Process Information}. diff --git a/etc/NEWS b/etc/NEWS index 1b1fec3e91..2ca91d5d79 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -379,6 +379,16 @@ displayed to be horizontally scrolled when lines are truncated on display and point moves outside the left or right window margin. +++ +** New mode line constructs '%o' and '%q', and user option +'mode-line-percent-position'. '%o' displays the "degree of travel" of +the window through the buffer. Unlike the default '%p', this +percentage approaches 100% as the window approaches the end of the +buffer. '%q' displays the percentage offsets of both the start and +the end of the window, e.g. "5-17%". The new option +'mode-line-percent-position' makes it easier to switch between '%p', +'%P', and these new constructs. + ++++ ** Two new user options 'list-matching-lines-jump-to-current-line' and 'list-matching-lines-current-line-face' to show highlighted the current line in *Occur* buffer. diff --git a/lisp/bindings.el b/lisp/bindings.el index 85a5408717..0b4c3bda80 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -365,14 +365,32 @@ zero, otherwise they start from one." :group 'mode-line :version "26.1") +(defcustom mode-line-percent-position '(-3 "%p") + "Specification of \"percentage offset\" of window through buffer +This option specifies both the field width and the type of offset +displayed in `mode-line-position', a component of the default +`mode-line-format'." + :type `(radio + (const :tag "nil: No offset is displayed" nil) + (const :tag "\"%o\": Proportion of \"travel\" of the window through the buffer" + (-3 "%o")) + (const :tag "\"%p\": Percentage offset of top of window" + (-3 "%p")) + (const :tag "\"%P\": Precentage offset of bottom of window" + (-3 "%P")) + (const :tag "\"%q\": Offsets of both top and bottom of window" + (6 "%q"))) + :version "26.1" + :group 'mode-line) + (defvar mode-line-position - `((-3 ,(propertize - "%p" - 'local-map mode-line-column-line-number-mode-map - 'mouse-face 'mode-line-highlight - ;; XXX needs better description - 'help-echo "Size indication mode\n\ -mouse-1: Display Line and Column Mode Menu")) + `((:propertize + mode-line-percent-position + 'local-map mode-line-column-line-number-mode-map + 'mouse-face 'mode-line-highlight + ;; XXX needs better description + 'help-echo "Size indication mode\n\ +mouse-1: Display Line and Column Mode Menu") (size-indication-mode (8 ,(propertize " of %I" diff --git a/src/xdisp.c b/src/xdisp.c index c0e821a934..0588061738 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23924,6 +23924,27 @@ decode_mode_spec (struct window *w, register int c, int field_width, return " Narrow"; break; + /* Display the "degree of travel" of the window through the buffer. */ + case 'o': + { + ptrdiff_t toppos = marker_position (w->start); + ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos; + ptrdiff_t begv = BUF_BEGV (b); + ptrdiff_t zv = BUF_ZV (b); + + if (zv <= botpos) + return toppos <= begv ? "All" : "Bottom"; + else if (toppos <= begv) + return "Top"; + else + { + sprintf (decode_mode_spec_buf, "%2d%%", + percent99 (toppos - begv, (toppos - begv) + (zv - botpos))); + return decode_mode_spec_buf; + } + } + + /* Display percentage of buffer above the top of the screen. */ case 'p': { ptrdiff_t pos = marker_position (w->start); @@ -23961,6 +23982,33 @@ decode_mode_spec (struct window *w, register int c, int field_width, } } + /* Display percentage offsets of top and bottom of the window, + using "All" (but not "Top" or "Bottom") where appropriate. */ + case 'q': + { + ptrdiff_t toppos = marker_position (w->start); + ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos; + ptrdiff_t begv = BUF_BEGV (b); + ptrdiff_t zv = BUF_ZV (b); + + if ((toppos <= begv) && (zv <= botpos)) + return "All "; + + if (toppos <= begv) + strcpy (decode_mode_spec_buf, "0-"); + else + sprintf (decode_mode_spec_buf, "%d-", + percent99 (toppos - begv, zv - begv)); + + if (zv <= botpos) + strcat (decode_mode_spec_buf, "100%"); + else + sprintf (&decode_mode_spec_buf [strlen (decode_mode_spec_buf)], + "%d%%", percent99 (botpos - begv, zv - begv)); + + return decode_mode_spec_buf; + } + case 's': /* status of process */ obj = Fget_buffer_process (Fcurrent_buffer ()); commit 9759b249e97d4b05644309fc70ae9277b347027e Author: Paul Eggert Date: Sun May 21 02:00:02 2017 -0700 Work around macOS bug in create_process, too * src/process.c (create_process) [DARWIN_OS]: Reset SIGCHLD after vfork here, too. diff --git a/src/process.c b/src/process.c index c30173955d..2a1c2eecde 100644 --- a/src/process.c +++ b/src/process.c @@ -2051,11 +2051,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) #ifdef DARWIN_OS /* Darwin doesn't let us run setsid after a vfork, so use fork when - necessary. */ + necessary. Also, reset SIGCHLD handling after a vfork, as + apparently macOS can mistakenly deliver SIGCHLD to the child. */ if (pty_flag) pid = fork (); else - pid = vfork (); + { + pid = vfork (); + if (pid == 0) + signal (SIGCHLD, SIG_DFL); + } #else pid = vfork (); #endif commit cb6d66974416f535fefb42c974b73037e257399a Author: Paul Eggert Date: Sun May 21 01:46:44 2017 -0700 Work around macOS bug with vforked child * src/callproc.c (call_process) [DARWIN_OS]: Include workaround for apparent macOS bug. diff --git a/src/callproc.c b/src/callproc.c index 7c85eed835..4cec02be7e 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -631,6 +631,14 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, if (pid == 0) { +#ifdef DARWIN_OS + /* Work around a macOS bug, where SIGCHLD is apparently + delivered to a vforked child instead of to its parent. See: + http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00342.html + */ + signal (SIGCHLD, SIG_DFL); +#endif + unblock_child_signal (&oldset); #ifdef DARWIN_OS commit 97c7a61d90987e182c1d2ec40fbe0d1d7df844c5 Author: Paul Eggert Date: Sun May 21 01:45:34 2017 -0700 Pacify --enable-gcc-warnings without modules * src/print.c (print_vectorlike): New function, taken from part of print_object. This one is indented properly, and pacifies --enable-gcc-warnings by using a default case instead of listing all the enum values, sometimes incompletely. (print_object): Use it. diff --git a/src/print.c b/src/print.c index be2e16a749..49408bbeb4 100644 --- a/src/print.c +++ b/src/print.c @@ -1346,6 +1346,371 @@ print_prune_string_charset (Lisp_Object string) return string; } +static bool +print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, + char *buf) +{ + switch (PSEUDOVECTOR_TYPE (XVECTOR (obj))) + { + case PVEC_PROCESS: + if (escapeflag) + { + print_c_string ("#name, printcharfun); + printchar ('>', printcharfun); + } + else + print_string (XPROCESS (obj)->name, printcharfun); + break; + + case PVEC_BOOL_VECTOR: + { + EMACS_INT size = bool_vector_size (obj); + ptrdiff_t size_in_chars = bool_vector_bytes (size); + ptrdiff_t real_size_in_chars = size_in_chars; + + int len = sprintf (buf, "#&%"pI"d\"", size); + strout (buf, len, len, printcharfun); + + /* Don't print more characters than the specified maximum. + Negative values of print-length are invalid. Treat them + like a print-length of nil. */ + if (NATNUMP (Vprint_length) + && XFASTINT (Vprint_length) < size_in_chars) + size_in_chars = XFASTINT (Vprint_length); + + for (ptrdiff_t i = 0; i < size_in_chars; i++) + { + maybe_quit (); + unsigned char c = bool_vector_uchar_data (obj)[i]; + if (c == '\n' && print_escape_newlines) + print_c_string ("\\n", printcharfun); + else if (c == '\f' && print_escape_newlines) + print_c_string ("\\f", printcharfun); + else if (c > '\177') + { + /* Use octal escapes to avoid encoding issues. */ + int len = sprintf (buf, "\\%o", c); + strout (buf, len, len, printcharfun); + } + else + { + if (c == '\"' || c == '\\') + printchar ('\\', printcharfun); + printchar (c, printcharfun); + } + } + + if (size_in_chars < real_size_in_chars) + print_c_string (" ...", printcharfun); + printchar ('\"', printcharfun); + } + break; + + case PVEC_SUBR: + print_c_string ("#symbol_name, printcharfun); + printchar ('>', printcharfun); + break; + + case PVEC_XWIDGET: case PVEC_XWIDGET_VIEW: + print_c_string ("#', printcharfun); + break; + + case PVEC_WINDOW: + { + int len = sprintf (buf, "#sequence_number); + strout (buf, len, len, printcharfun); + if (BUFFERP (XWINDOW (obj)->contents)) + { + print_c_string (" on ", printcharfun); + print_string (BVAR (XBUFFER (XWINDOW (obj)->contents), name), + printcharfun); + } + printchar ('>', printcharfun); + } + break; + + case PVEC_TERMINAL: + { + struct terminal *t = XTERMINAL (obj); + int len = sprintf (buf, "#id); + strout (buf, len, len, printcharfun); + if (t->name) + { + print_c_string (" on ", printcharfun); + print_c_string (t->name, printcharfun); + } + printchar ('>', printcharfun); + } + break; + + case PVEC_HASH_TABLE: + { + struct Lisp_Hash_Table *h = XHASH_TABLE (obj); + /* Implement a readable output, e.g.: + #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ + /* Always print the size. */ + int len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next)); + strout (buf, len, len, printcharfun); + + if (!NILP (h->test.name)) + { + print_c_string (" test ", printcharfun); + print_object (h->test.name, printcharfun, escapeflag); + } + + if (!NILP (h->weak)) + { + print_c_string (" weakness ", printcharfun); + print_object (h->weak, printcharfun, escapeflag); + } + + print_c_string (" rehash-size ", printcharfun); + print_object (Fhash_table_rehash_size (obj), + printcharfun, escapeflag); + + print_c_string (" rehash-threshold ", printcharfun); + print_object (Fhash_table_rehash_threshold (obj), + printcharfun, escapeflag); + + if (h->pure) + { + print_c_string (" purecopy ", printcharfun); + print_object (h->pure ? Qt : Qnil, printcharfun, escapeflag); + } + + print_c_string (" data ", printcharfun); + + /* Print the data here as a plist. */ + ptrdiff_t real_size = HASH_TABLE_SIZE (h); + ptrdiff_t size = real_size; + + /* Don't print more elements than the specified maximum. */ + if (NATNUMP (Vprint_length) && XFASTINT (Vprint_length) < size) + size = XFASTINT (Vprint_length); + + printchar ('(', printcharfun); + for (ptrdiff_t i = 0; i < size; i++) + if (!NILP (HASH_HASH (h, i))) + { + if (i) printchar (' ', printcharfun); + print_object (HASH_KEY (h, i), printcharfun, escapeflag); + printchar (' ', printcharfun); + print_object (HASH_VALUE (h, i), printcharfun, escapeflag); + } + + if (size < real_size) + print_c_string (" ...", printcharfun); + + print_c_string ("))", printcharfun); + } + break; + + case PVEC_BUFFER: + if (!BUFFER_LIVE_P (XBUFFER (obj))) + print_c_string ("#", printcharfun); + else if (escapeflag) + { + print_c_string ("#', printcharfun); + } + else + print_string (BVAR (XBUFFER (obj), name), printcharfun); + break; + + case PVEC_WINDOW_CONFIGURATION: + print_c_string ("#", printcharfun); + break; + + case PVEC_FRAME: + { + void *ptr = XFRAME (obj); + Lisp_Object frame_name = XFRAME (obj)->name; + + print_c_string ((FRAME_LIVE_P (XFRAME (obj)) + ? "#", ptr); + strout (buf, len, len, printcharfun); + } + break; + + case PVEC_FONT: + { + if (! FONT_OBJECT_P (obj)) + { + if (FONT_SPEC_P (obj)) + print_c_string ("# FONT_WIDTH_INDEX) + print_object (AREF (obj, i), printcharfun, escapeflag); + else + print_object (font_style_symbolic (obj, i, 0), + printcharfun, escapeflag); + } + } + else + { + print_c_string ("#', printcharfun); + } + break; + + case PVEC_THREAD: + print_c_string ("#name)) + print_string (XTHREAD (obj)->name, printcharfun); + else + { + int len = sprintf (buf, "%p", XTHREAD (obj)); + strout (buf, len, len, printcharfun); + } + printchar ('>', printcharfun); + break; + + case PVEC_MUTEX: + print_c_string ("#name)) + print_string (XMUTEX (obj)->name, printcharfun); + else + { + int len = sprintf (buf, "%p", XMUTEX (obj)); + strout (buf, len, len, printcharfun); + } + printchar ('>', printcharfun); + break; + + case PVEC_CONDVAR: + print_c_string ("#name)) + print_string (XCONDVAR (obj)->name, printcharfun); + else + { + int len = sprintf (buf, "%p", XCONDVAR (obj)); + strout (buf, len, len, printcharfun); + } + printchar ('>', printcharfun); + break; + + case PVEC_RECORD: + { + ptrdiff_t size = PVSIZE (obj); + + /* Don't print more elements than the specified maximum. */ + ptrdiff_t n + = (NATNUMP (Vprint_length) && XFASTINT (Vprint_length) < size + ? XFASTINT (Vprint_length) : size); + + print_c_string ("#s(", printcharfun); + for (ptrdiff_t i = 0; i < n; i ++) + { + if (i) printchar (' ', printcharfun); + print_object (AREF (obj, i), printcharfun, escapeflag); + } + if (n < size) + print_c_string (" ...", printcharfun); + printchar (')', printcharfun); + } + break; + + case PVEC_SUB_CHAR_TABLE: + case PVEC_COMPILED: + case PVEC_CHAR_TABLE: + case PVEC_NORMAL_VECTOR: + { + ptrdiff_t size = ASIZE (obj); + if (COMPILEDP (obj)) + { + printchar ('#', printcharfun); + size &= PSEUDOVECTOR_SIZE_MASK; + } + if (CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)) + { + /* Print a char-table as if it were a vector, + lumping the parent and default slots in with the + character slots. But add #^ as a prefix. */ + + /* Make each lowest sub_char_table start a new line. + Otherwise we'll make a line extremely long, which + results in slow redisplay. */ + if (SUB_CHAR_TABLE_P (obj) + && XSUB_CHAR_TABLE (obj)->depth == 3) + printchar ('\n', printcharfun); + print_c_string ("#^", printcharfun); + if (SUB_CHAR_TABLE_P (obj)) + printchar ('^', printcharfun); + size &= PSEUDOVECTOR_SIZE_MASK; + } + if (size & PSEUDOVECTOR_FLAG) + return false; + + printchar ('[', printcharfun); + + int idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0; + Lisp_Object tem; + ptrdiff_t real_size = size; + + /* For a sub char-table, print heading non-Lisp data first. */ + if (SUB_CHAR_TABLE_P (obj)) + { + int i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth, + XSUB_CHAR_TABLE (obj)->min_char); + strout (buf, i, i, printcharfun); + } + + /* Don't print more elements than the specified maximum. */ + if (NATNUMP (Vprint_length) + && XFASTINT (Vprint_length) < size) + size = XFASTINT (Vprint_length); + + for (int i = idx; i < size; i++) + { + if (i) printchar (' ', printcharfun); + tem = AREF (obj, i); + print_object (tem, printcharfun, escapeflag); + } + if (size < real_size) + print_c_string (" ...", printcharfun); + printchar (']', printcharfun); + } + break; + +#ifdef HAVE_MODULES + case PVEC_MODULE_FUNCTION: + print_string (module_format_fun_env (XMODULE_FUNCTION (obj)), + printcharfun); + break; +#endif + + default: + emacs_abort (); + } + + return true; +} + static void print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) { @@ -1678,390 +2043,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) break; case Lisp_Vectorlike: - switch (PSEUDOVECTOR_TYPE (XVECTOR (obj))) { - case PVEC_PROCESS: - { - if (escapeflag) - { - print_c_string ("#name, printcharfun); - printchar ('>', printcharfun); - } - else - print_string (XPROCESS (obj)->name, printcharfun); - } - break; - - case PVEC_BOOL_VECTOR: - { - ptrdiff_t i; - unsigned char c; - EMACS_INT size = bool_vector_size (obj); - ptrdiff_t size_in_chars = bool_vector_bytes (size); - ptrdiff_t real_size_in_chars = size_in_chars; - - int len = sprintf (buf, "#&%"pI"d\"", size); - strout (buf, len, len, printcharfun); - - /* Don't print more characters than the specified maximum. - Negative values of print-length are invalid. Treat them - like a print-length of nil. */ - if (NATNUMP (Vprint_length) - && XFASTINT (Vprint_length) < size_in_chars) - size_in_chars = XFASTINT (Vprint_length); - - for (i = 0; i < size_in_chars; i++) - { - maybe_quit (); - c = bool_vector_uchar_data (obj)[i]; - if (c == '\n' && print_escape_newlines) - print_c_string ("\\n", printcharfun); - else if (c == '\f' && print_escape_newlines) - print_c_string ("\\f", printcharfun); - else if (c > '\177') - { - /* Use octal escapes to avoid encoding issues. */ - len = sprintf (buf, "\\%o", c); - strout (buf, len, len, printcharfun); - } - else - { - if (c == '\"' || c == '\\') - printchar ('\\', printcharfun); - printchar (c, printcharfun); - } - } - - if (size_in_chars < real_size_in_chars) - print_c_string (" ...", printcharfun); - printchar ('\"', printcharfun); - } - break; - - case PVEC_SUBR: - { - print_c_string ("#symbol_name, printcharfun); - printchar ('>', printcharfun); - } - break; - - case PVEC_XWIDGET: case PVEC_XWIDGET_VIEW: - { - print_c_string ("#', printcharfun); - } - break; - - case PVEC_WINDOW: - { - int len = sprintf (buf, "#sequence_number); - strout (buf, len, len, printcharfun); - if (BUFFERP (XWINDOW (obj)->contents)) - { - print_c_string (" on ", printcharfun); - print_string (BVAR (XBUFFER (XWINDOW (obj)->contents), name), - printcharfun); - } - printchar ('>', printcharfun); - } - break; - - case PVEC_TERMINAL: - { - struct terminal *t = XTERMINAL (obj); - int len = sprintf (buf, "#id); - strout (buf, len, len, printcharfun); - if (t->name) - { - print_c_string (" on ", printcharfun); - print_c_string (t->name, printcharfun); - } - printchar ('>', printcharfun); - } - break; - - case PVEC_HASH_TABLE: - { - struct Lisp_Hash_Table *h = XHASH_TABLE (obj); - ptrdiff_t i; - ptrdiff_t real_size, size; - int len; - /* Implement a readable output, e.g.: - #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ - /* Always print the size. */ - len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next)); - strout (buf, len, len, printcharfun); - - if (!NILP (h->test.name)) - { - print_c_string (" test ", printcharfun); - print_object (h->test.name, printcharfun, escapeflag); - } - - if (!NILP (h->weak)) - { - print_c_string (" weakness ", printcharfun); - print_object (h->weak, printcharfun, escapeflag); - } - - print_c_string (" rehash-size ", printcharfun); - print_object (Fhash_table_rehash_size (obj), - printcharfun, escapeflag); - - print_c_string (" rehash-threshold ", printcharfun); - print_object (Fhash_table_rehash_threshold (obj), - printcharfun, escapeflag); - - if (h->pure) - { - print_c_string (" purecopy ", printcharfun); - print_object (h->pure ? Qt : Qnil, printcharfun, escapeflag); - } - - print_c_string (" data ", printcharfun); - - /* Print the data here as a plist. */ - real_size = HASH_TABLE_SIZE (h); - size = real_size; - - /* Don't print more elements than the specified maximum. */ - if (NATNUMP (Vprint_length) - && XFASTINT (Vprint_length) < size) - size = XFASTINT (Vprint_length); - - printchar ('(', printcharfun); - for (i = 0; i < size; i++) - if (!NILP (HASH_HASH (h, i))) - { - if (i) printchar (' ', printcharfun); - print_object (HASH_KEY (h, i), printcharfun, escapeflag); - printchar (' ', printcharfun); - print_object (HASH_VALUE (h, i), printcharfun, escapeflag); - } - - if (size < real_size) - print_c_string (" ...", printcharfun); - - print_c_string ("))", printcharfun); - } - break; - - case PVEC_BUFFER: - { - if (!BUFFER_LIVE_P (XBUFFER (obj))) - print_c_string ("#", printcharfun); - else if (escapeflag) - { - print_c_string ("#', printcharfun); - } - else - print_string (BVAR (XBUFFER (obj), name), printcharfun); - } - break; - - case PVEC_WINDOW_CONFIGURATION: - print_c_string ("#", printcharfun); - break; - - case PVEC_FRAME: ; - { - int len; - void *ptr = XFRAME (obj); - Lisp_Object frame_name = XFRAME (obj)->name; - - print_c_string ((FRAME_LIVE_P (XFRAME (obj)) - ? "#", ptr); - strout (buf, len, len, printcharfun); - } - break; - - case PVEC_FONT: - { - int i; - - if (! FONT_OBJECT_P (obj)) - { - if (FONT_SPEC_P (obj)) - print_c_string ("# FONT_WIDTH_INDEX) - print_object (AREF (obj, i), printcharfun, escapeflag); - else - print_object (font_style_symbolic (obj, i, 0), - printcharfun, escapeflag); - } - } - else - { - print_c_string ("#', printcharfun); - } - break; - - case PVEC_THREAD: - { - print_c_string ("#name)) - print_string (XTHREAD (obj)->name, printcharfun); - else - { - int len = sprintf (buf, "%p", XTHREAD (obj)); - strout (buf, len, len, printcharfun); - } - printchar ('>', printcharfun); - } - break; - - case PVEC_MUTEX: - { - print_c_string ("#name)) - print_string (XMUTEX (obj)->name, printcharfun); - else - { - int len = sprintf (buf, "%p", XMUTEX (obj)); - strout (buf, len, len, printcharfun); - } - printchar ('>', printcharfun); - } - break; - - case PVEC_CONDVAR: - { - print_c_string ("#name)) - print_string (XCONDVAR (obj)->name, printcharfun); - else - { - int len = sprintf (buf, "%p", XCONDVAR (obj)); - strout (buf, len, len, printcharfun); - } - printchar ('>', printcharfun); - } - break; - - case PVEC_RECORD: - { - ptrdiff_t n, size = PVSIZE (obj); - int i; - - /* Don't print more elements than the specified maximum. */ - if (NATNUMP (Vprint_length) - && XFASTINT (Vprint_length) < size) - n = XFASTINT (Vprint_length); - else - n = size; - - print_c_string ("#s(", printcharfun); - for (i = 0; i < n; i ++) - { - if (i) printchar (' ', printcharfun); - print_object (AREF (obj, i), printcharfun, escapeflag); - } - if (n < size) - print_c_string (" ...", printcharfun); - printchar (')', printcharfun); - } - break; - - case PVEC_SUB_CHAR_TABLE: - case PVEC_COMPILED: - case PVEC_CHAR_TABLE: - case PVEC_NORMAL_VECTOR: ; - { - ptrdiff_t size = ASIZE (obj); - if (COMPILEDP (obj)) - { - printchar ('#', printcharfun); - size &= PSEUDOVECTOR_SIZE_MASK; - } - if (CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)) - { - /* We print a char-table as if it were a vector, - lumping the parent and default slots in with the - character slots. But we add #^ as a prefix. */ - - /* Make each lowest sub_char_table start a new line. - Otherwise we'll make a line extremely long, which - results in slow redisplay. */ - if (SUB_CHAR_TABLE_P (obj) - && XSUB_CHAR_TABLE (obj)->depth == 3) - printchar ('\n', printcharfun); - print_c_string ("#^", printcharfun); - if (SUB_CHAR_TABLE_P (obj)) - printchar ('^', printcharfun); - size &= PSEUDOVECTOR_SIZE_MASK; - } - if (size & PSEUDOVECTOR_FLAG) - goto badtype; - - printchar ('[', printcharfun); - { - int i, idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0; - Lisp_Object tem; - ptrdiff_t real_size = size; - - /* For a sub char-table, print heading non-Lisp data first. */ - if (SUB_CHAR_TABLE_P (obj)) - { - i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth, - XSUB_CHAR_TABLE (obj)->min_char); - strout (buf, i, i, printcharfun); - } - - /* Don't print more elements than the specified maximum. */ - if (NATNUMP (Vprint_length) - && XFASTINT (Vprint_length) < size) - size = XFASTINT (Vprint_length); - - for (i = idx; i < size; i++) - { - if (i) printchar (' ', printcharfun); - tem = AREF (obj, i); - print_object (tem, printcharfun, escapeflag); - } - if (size < real_size) - print_c_string (" ...", printcharfun); - } - printchar (']', printcharfun); - } - break; - -#ifdef HAVE_MODULES - case PVEC_MODULE_FUNCTION: - print_string (module_format_fun_env (XMODULE_FUNCTION (obj)), - printcharfun); - break; -#endif - - case PVEC_OTHER: - case PVEC_FREE: - emacs_abort (); - } + if (! print_vectorlike (obj, printcharfun, escapeflag, buf)) + goto badtype; break; case Lisp_Misc: commit b35293dfd0e9dd95a88ac01051655d0d2d105992 Author: Paul Eggert Date: Sat May 20 22:55:17 2017 -0700 Remove DARWIN_OS_CASE_SENSITIVE_FIXME code It does not appear to be needed (Bug#24441). * etc/PROBLEMS: Remove DARWIN_OS_CASE_SENSITIVE_FIXME stuff. * src/fileio.c (file_name_case_insensitive_p): Remove DARWIN_OS_CASE_SENSITIVE_FIXME code. diff --git a/etc/PROBLEMS b/etc/PROBLEMS index ff88aa367f..593eb6b745 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2479,16 +2479,6 @@ please call support for your X-server and see if you can get a fix. If you do, please send it to bug-gnu-emacs@gnu.org so we can list it here. -* Runtime problems specific to Mac OS X - -** On Mac OS X, file-name-case-insensitive-p may be unreliable - -The implementation of that function on Mac OS X uses pathconf with the -_PC_CASE_SENSITIVE flag. There have been reports that this use of -pathconf does not work reliably. If you have a problem, please -recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME, and file a bug -report saying whether this fixed your problem. - * Build-time problems ** Configuration diff --git a/src/fileio.c b/src/fileio.c index 17659b692e..c21056ee6f 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2271,27 +2271,6 @@ file_name_case_insensitive_p (const char *filename) return res == 0; #endif - /* There have been reports that pathconf with _PC_CASE_SENSITIVE - does not work reliably on Mac OS X. If you have a problem, - please recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME=1 or - -D DARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying - whether this fixed your problem. */ - -#ifdef DARWIN_OS_CASE_SENSITIVE_FIXME -# ifdef VOL_CAP_FMT_CASE_SENSITIVE - { - struct attrlist alist = {.bitmapcount = ATTR_BIT_MAP_COUNT, - .volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES}; - struct { uint32_t len; vol_capabilities_attr_t caps; } vcaps - __attribute__ ((aligned (4), packed)); - int i = VOL_CAPABILITIES_FORMAT; - if (getattrlist (filename, &alist, &vcaps, sizeof vcaps, 0) == 0 - && (vcaps.caps.valid[i] & VOL_CAP_FMT_CASE_SENSITIVE)) - return ! (vcaps.caps.capabilities[i] & VOL_CAP_FMT_CASE_SENSITIVE); - } -# endif -#endif - #if defined CYGWIN || defined DOS_NT return true; #else commit 075bd64609446e741a6efbcd6cd6e232db8d1df6 Author: Paul Eggert Date: Sat May 20 22:51:32 2017 -0700 Narrow DARWIN_OS_CASE_SENSITIVE_FIXME to 1 choice * etc/PROBLEMS: Document this (Bug#24441). * src/fileio.c (file_name_case_insensitive_p): Prefer pathconf with _PC_CASE_SENSITIVE, if it works, to DARWIN_OS_CASE_SENSITIVE_FIXME code. Support just one method for DARWIN_OS_CASE_SENSITIVE_FIXME, which matches the Apple documentation more precisely. diff --git a/etc/PROBLEMS b/etc/PROBLEMS index e415887a4d..ff88aa367f 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2486,9 +2486,8 @@ If you do, please send it to bug-gnu-emacs@gnu.org so we can list it here. The implementation of that function on Mac OS X uses pathconf with the _PC_CASE_SENSITIVE flag. There have been reports that this use of pathconf does not work reliably. If you have a problem, please -recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME=1 or --D DARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying -whether this fixed your problem. +recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME, and file a bug +report saying whether this fixed your problem. * Build-time problems diff --git a/src/fileio.c b/src/fileio.c index e5e350542f..17659b692e 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2256,65 +2256,41 @@ static bool file_name_case_insensitive_p (const char *filename) { /* Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if - those flags are available. As of this writing (2016-11-14), + those flags are available. As of this writing (2017-05-20), Cygwin is the only platform known to support the former (starting - with Cygwin-2.6.1), and Mac OS X is the only platform known to - support the latter. - - There have been reports that pathconf with _PC_CASE_SENSITIVE - does not work reliably on Mac OS X. If you have a problem, - please recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME=1 or - -D DARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying - whether this fixed your problem. */ + with Cygwin-2.6.1), and macOS is the only platform known to + support the latter. */ #ifdef _PC_CASE_INSENSITIVE int res = pathconf (filename, _PC_CASE_INSENSITIVE); if (res >= 0) return res > 0; -#elif defined _PC_CASE_SENSITIVE && !defined DARWIN_OS_CASE_SENSITIVE_FIXME +#elif defined _PC_CASE_SENSITIVE int res = pathconf (filename, _PC_CASE_SENSITIVE); if (res >= 0) return res == 0; #endif -#ifdef DARWIN_OS -# ifndef DARWIN_OS_CASE_SENSITIVE_FIXME - int DARWIN_OS_CASE_SENSITIVE_FIXME = 0; -# endif + /* There have been reports that pathconf with _PC_CASE_SENSITIVE + does not work reliably on Mac OS X. If you have a problem, + please recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME=1 or + -D DARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying + whether this fixed your problem. */ - if (DARWIN_OS_CASE_SENSITIVE_FIXME == 1) - { - /* This is based on developer.apple.com's getattrlist man page. */ - struct attrlist alist = {.volattr = ATTR_VOL_CAPABILITIES}; - vol_capabilities_attr_t vcaps; - if (getattrlist (filename, &alist, &vcaps, sizeof vcaps, 0) == 0) - { - if (vcaps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE) - return ! (vcaps.capabilities[VOL_CAPABILITIES_FORMAT] - & VOL_CAP_FMT_CASE_SENSITIVE); - } - } -# if DARWIN_OS_CASE_SENSITIVE_FIXME == 2 - { - /* The following is based on - http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html. - It is normally not even compiled, since it runs afoul of - static checking. See: - http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00495.html - */ - struct attrlist alist; - unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)]; - - memset (&alist, 0, sizeof (alist)); - alist.volattr = ATTR_VOL_CAPABILITIES; - if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0) - || !(alist.volattr & ATTR_VOL_CAPABILITIES)) - return 0; - vol_capabilities_attr_t *vcaps = buffer; - return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE); - } +#ifdef DARWIN_OS_CASE_SENSITIVE_FIXME +# ifdef VOL_CAP_FMT_CASE_SENSITIVE + { + struct attrlist alist = {.bitmapcount = ATTR_BIT_MAP_COUNT, + .volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES}; + struct { uint32_t len; vol_capabilities_attr_t caps; } vcaps + __attribute__ ((aligned (4), packed)); + int i = VOL_CAPABILITIES_FORMAT; + if (getattrlist (filename, &alist, &vcaps, sizeof vcaps, 0) == 0 + && (vcaps.caps.valid[i] & VOL_CAP_FMT_CASE_SENSITIVE)) + return ! (vcaps.caps.capabilities[i] & VOL_CAP_FMT_CASE_SENSITIVE); + } # endif -#endif /* DARWIN_OS */ +#endif #if defined CYGWIN || defined DOS_NT return true; commit 2963861f3d4070420eeee0791008f3e1c02a0450 Author: Tom Tromey Date: Sat May 20 22:01:15 2017 -0600 Fix mhtml-mode fontification bug Bug#26922 * lisp/textmodes/mhtml-mode.el (mhtml-syntax-propertize): Call sgml-syntax-propertize-inside if not in a submode. * test/manual/indent/html-multi-4.html: New file. diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el index a0fa8492cf..2f2257d96b 100644 --- a/lisp/textmodes/mhtml-mode.el +++ b/lisp/textmodes/mhtml-mode.el @@ -283,14 +283,16 @@ can function properly.") (remove-list-of-text-properties start end '(syntax-table local-map mhtml-submode)) (goto-char start) - (when (and - ;; Don't search in a comment or string - (not (syntax-ppss-context (syntax-ppss))) - ;; Be sure to look back one character, because START won't - ;; yet have been propertized. - (not (bobp))) - (when-let ((submode (get-text-property (1- (point)) 'mhtml-submode))) - (mhtml--syntax-propertize-submode submode end))) + ;; Be sure to look back one character, because START won't yet have + ;; been propertized. + (unless (bobp) + (let ((submode (get-text-property (1- (point)) 'mhtml-submode))) + (if submode + ;; Don't search in a comment or string + (unless (syntax-ppss-context (syntax-ppss)) + (mhtml--syntax-propertize-submode submode end)) + ;; No submode, so do what sgml-mode does. + (sgml-syntax-propertize-inside end)))) (funcall (syntax-propertize-rules ("" diff --git a/test/manual/indent/html-multi-4.html b/test/manual/indent/html-multi-4.html new file mode 100644 index 0000000000..0eb89d17b0 --- /dev/null +++ b/test/manual/indent/html-multi-4.html @@ -0,0 +1,15 @@ + + + + + + +

This is a test.

+ + + commit f422b46eb1d3c62c912ee0806486d017f5153e54 Author: Ryan Date: Fri May 19 11:07:57 2017 -0400 Fix ido-enable-dot-prefix for empty choice (Bug#26997) * lisp/ido.el (ido-set-matches-1): Only check first character of item if it's non-empty. Copyright-paperwork-exempt: yes diff --git a/lisp/ido.el b/lisp/ido.el index 1393d3b710..07a5bcf722 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -3802,9 +3802,10 @@ frame, rather than all frames, regardless of value of `ido-all-frames'." (lambda (item) (let ((name (ido-name item))) (if (and (or non-prefix-dot - (if (= (aref ido-text 0) ?.) - (= (aref name 0) ?.) - (/= (aref name 0) ?.))) + (and (> (length name) 0) + (if (= (aref ido-text 0) ?.) + (= (aref name 0) ?.) + (/= (aref name 0) ?.)))) (string-match re name)) (cond ((and (eq ido-cur-item 'buffer) commit 547f78c813c7f792a892a2ee16664b133067f9bc Author: Ari Roponen Date: Sat May 20 17:14:36 2017 -0700 * lisp/svg.el (svg-line): Fix x/y typo. (Bug#26953) diff --git a/lisp/svg.el b/lisp/svg.el index cb924f8163..fc1a6d60e1 100644 --- a/lisp/svg.el +++ b/lisp/svg.el @@ -107,8 +107,8 @@ X/Y denote the center of the ellipse." svg (dom-node 'line `((x1 . ,x1) - (x2 . ,y1) - (y1 . ,x2) + (x2 . ,x2) + (y1 . ,y1) (y2 . ,y2) ,@(svg--arguments svg args))))) commit 7f4e5ca8fb40ce13d7fd7979171ba87fe39cb254 Author: Glenn Morris Date: Sat May 20 17:05:18 2017 -0700 Prevent loading vc-bzr writing to ~/.bzr.log * lisp/vc/vc-bzr.el (vc-bzr-status-switches): Disable bzr logging. diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el index 73d05c7bfc..d0e9f7744b 100644 --- a/lisp/vc/vc-bzr.el +++ b/lisp/vc/vc-bzr.el @@ -98,7 +98,9 @@ If nil, use the value of `vc-annotate-switches'. If t, use no switches." (defcustom vc-bzr-status-switches (ignore-errors (with-temp-buffer - (call-process vc-bzr-program nil t nil "help" "status") + (let ((process-environment (cons (format "BZR_LOG=%s" null-device) + process-environment))) + (call-process vc-bzr-program nil t nil "help" "status")) (if (search-backward "--no-classify" nil t) "--no-classify"))) "String or list of strings specifying switches for bzr status under VC. commit ed8b4e0c0c5da838e639d1505bdd090a7e2d735f Author: Glenn Morris Date: Sat May 20 17:00:02 2017 -0700 Prevent running vc-tests writing to ~/.bzr.log * test/lisp/vc/vc-tests.el (vc-test--create-repo) (vc-test--register, vc-test--working-revision) (vc-test--checkout-model): Set temporary BZR_HOME, to disable logging. diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el index 656f673b20..1104085a2e 100644 --- a/test/lisp/vc/vc-tests.el +++ b/test/lisp/vc/vc-tests.el @@ -115,7 +115,7 @@ (defvar vc-test--cleanup-hook nil "Functions for cleanup at the end of an ert test. -Don't set it globally, the functions shall be let-bound.") +Don't set it globally, the functions should be let-bound.") (defun vc-test--revision-granularity-function (backend) "Run the `vc-revision-granularity' backend function." @@ -181,7 +181,13 @@ For backends which dont support it, it is emulated." (file-name-as-directory (expand-file-name (make-temp-name "vc-test") temporary-file-directory))) + (process-environment process-environment) + tempdir vc-test--cleanup-hook) + (when (eq backend 'Bzr) + (setq tempdir (make-temp-file "vc-test--create-repo" t) + process-environment (cons (format "BZR_HOME=%s" tempdir) + process-environment))) (unwind-protect (progn @@ -201,7 +207,9 @@ For backends which dont support it, it is emulated." (should (eq (vc-responsible-backend default-directory) backend))) ;; Save exit. - (ignore-errors (run-hooks 'vc-test--cleanup-hook))))) + (ignore-errors + (if tempdir (delete-directory tempdir t)) + (run-hooks 'vc-test--cleanup-hook))))) ;; FIXME: Why isn't there `vc-unregister'? (defun vc-test--unregister-function (backend file) @@ -231,8 +239,13 @@ This checks also `vc-backend' and `vc-responsible-backend'." (file-name-as-directory (expand-file-name (make-temp-name "vc-test") temporary-file-directory))) + (process-environment process-environment) + tempdir vc-test--cleanup-hook) - + (when (eq backend 'Bzr) + (setq tempdir (make-temp-file "vc-test--register" t) + process-environment (cons (format "BZR_HOME=%s" tempdir) + process-environment))) (unwind-protect (progn ;; Cleanup. @@ -292,12 +305,14 @@ This checks also `vc-backend' and `vc-responsible-backend'." (should-not (vc-backend tmp-name2)) (should-not (vc-registered tmp-name2))) - ;; The files shall still exist. + ;; The files should still exist. (should (file-exists-p tmp-name1)) (should (file-exists-p tmp-name2)))) ;; Save exit. - (ignore-errors (run-hooks 'vc-test--cleanup-hook))))) + (ignore-errors + (if tempdir (delete-directory tempdir t)) + (run-hooks 'vc-test--cleanup-hook))))) (defun vc-test--state (backend) "Check the different states of a file." @@ -374,7 +389,13 @@ This checks also `vc-backend' and `vc-responsible-backend'." (file-name-as-directory (expand-file-name (make-temp-name "vc-test") temporary-file-directory))) + (process-environment process-environment) + tempdir vc-test--cleanup-hook) + (when (eq backend 'Bzr) + (setq tempdir (make-temp-file "vc-test--working-revision" t) + process-environment (cons (format "BZR_HOME=%s" tempdir) + process-environment))) (unwind-protect (progn @@ -435,7 +456,9 @@ This checks also `vc-backend' and `vc-responsible-backend'." (should-not (vc-working-revision tmp-name))))) ;; Save exit. - (ignore-errors (run-hooks 'vc-test--cleanup-hook))))) + (ignore-errors + (if tempdir (delete-directory tempdir t)) + (run-hooks 'vc-test--cleanup-hook))))) (defun vc-test--checkout-model (backend) "Check the checkout model of a repository." @@ -445,7 +468,13 @@ This checks also `vc-backend' and `vc-responsible-backend'." (file-name-as-directory (expand-file-name (make-temp-name "vc-test") temporary-file-directory))) + (process-environment process-environment) + tempdir vc-test--cleanup-hook) + (when (eq backend 'Bzr) + (setq tempdir (make-temp-file "vc-test--checkout-model" t) + process-environment (cons (format "BZR_HOME=%s" tempdir) + process-environment))) (unwind-protect (progn @@ -512,7 +541,9 @@ This checks also `vc-backend' and `vc-responsible-backend'." '(announce implicit locking)))))) ;; Save exit. - (ignore-errors (run-hooks 'vc-test--cleanup-hook))))) + (ignore-errors + (if tempdir (delete-directory tempdir t)) + (run-hooks 'vc-test--cleanup-hook))))) ;; Create the test cases. commit abd098200bfba2577dfff800f27d5474f13cc1f3 Author: Noam Postavsky Date: Sat May 20 19:11:51 2017 -0400 Don't end non-hook variable with "-hook" (Bug#26623) * lisp/follow.el (follow-inside-post-command-hook-call): Renamed from follow-inside-post-command-hook, update uses. diff --git a/lisp/follow.el b/lisp/follow.el index db3b2821a5..5dd74f37a1 100644 --- a/lisp/follow.el +++ b/lisp/follow.el @@ -340,7 +340,7 @@ property `follow-mode-use-cache' to non-nil.") (defvar follow-inactive-menu nil "The menu visible when Follow mode is inactive.") -(defvar follow-inside-post-command-hook nil +(defvar follow-inside-post-command-hook-call nil "Non-nil when inside Follow modes `post-command-hook'. Used by `follow-window-size-change'.") @@ -1277,7 +1277,7 @@ non-first windows in Follow mode." (defun follow-post-command-hook () "Ensure that the windows in Follow mode are adjacent after each command." (unless (input-pending-p) - (let ((follow-inside-post-command-hook t) + (let ((follow-inside-post-command-hook-call t) (win (selected-window))) ;; Work in the selected window, not in the current buffer. (with-current-buffer (window-buffer win) @@ -1519,14 +1519,14 @@ non-first windows in Follow mode." ;; Since `follow-window-size-change' can be called indirectly from ;; `follow-post-command-hook' we have a potential infinite loop. To ;; avoid this, we simply do not do anything in this situation. The -;; variable `follow-inside-post-command-hook' contains information -;; about whether the execution actually is inside the +;; variable `follow-inside-post-command-hook-call' contains +;; information about whether the execution actually is inside the ;; post-command-hook or not. (defun follow-window-size-change (frame) "Redraw all windows in FRAME, when in Follow mode." ;; Below, we call `post-command-hook'. Avoid an infloop. - (unless follow-inside-post-command-hook + (unless follow-inside-post-command-hook-call (save-current-buffer (let ((orig-frame (selected-frame))) (select-frame frame) commit 7e5a8cdceb408077df78b1ea810b1f5d4657303d Author: Charles A. Roelli Date: Thu May 18 21:31:46 2017 +0200 Fix macOS mouse movement * lisp/frame.el (ns-set-mouse-absolute-pixel-position): New function (Lisp). (set-mouse-absolute-pixel-position): Change it to call `ns-set-mouse-absolute-pixel-position' on macOS. * src/nsfns.m (Fns_set_mouse_absolute_pixel_position): New function. * src/nsterm.h (NS_PARENT_WINDOW_TOP_POS): Use the primary screen's height as a base for calculating global coordinates. * src/nsterm.m (frame_set_mouse_pixel_position): Fix it in macOS. * test/lisp/mouse-tests.el (bug26816-mouse-frame-movement): Test movement of mouse relative to frame. diff --git a/etc/NEWS b/etc/NEWS index eeb7c773ac..1b1fec3e91 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1321,6 +1321,9 @@ This is in contrast to the default action on POSIX Systems, where it causes the receiving process to terminate with a core dump if no debugger has been attached to it. +** `set-mouse-position' and `set-mouse-absolute-pixel-position' work +on macOS. + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/lisp/frame.el b/lisp/frame.el index 05db8cf6fd..02871e0551 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1465,6 +1465,7 @@ position (0, 0) of the selected frame's terminal." (t (cons 0 0))))) +(declare-function ns-set-mouse-absolute-pixel-position "nsfns.m" (x y)) (declare-function w32-set-mouse-absolute-pixel-position "w32fns.c" (x y)) (declare-function x-set-mouse-absolute-pixel-position "xfns.c" (x y)) @@ -1474,6 +1475,8 @@ The coordinates X and Y are interpreted in pixels relative to a position (0, 0) of the selected frame's terminal." (let ((frame-type (framep-on-display))) (cond + ((eq frame-type 'ns) + (ns-set-mouse-absolute-pixel-position x y)) ((eq frame-type 'x) (x-set-mouse-absolute-pixel-position x y)) ((eq frame-type 'w32) diff --git a/src/nsfns.m b/src/nsfns.m index 04565a99bb..a815ce656c 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -3066,6 +3066,44 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are : Qnative_edges)); } +DEFUN ("ns-set-mouse-absolute-pixel-position", + Fns_set_mouse_absolute_pixel_position, + Sns_set_mouse_absolute_pixel_position, 2, 2, 0, + doc: /* Move mouse pointer to absolute pixel position (X, Y). +The coordinates X and Y are interpreted in pixels relative to a position +\(0, 0) of the selected frame's display. */) + (Lisp_Object x, Lisp_Object y) +{ + struct frame *f = SELECTED_FRAME (); + EmacsView *view = FRAME_NS_VIEW (f); + NSScreen *screen = [[view window] screen]; + NSRect screen_frame = [screen frame]; + int mouse_x, mouse_y; + + NSScreen *primary_screen = [[NSScreen screens] objectAtIndex:0]; + NSRect primary_screen_frame = [primary_screen frame]; + CGFloat primary_screen_height = primary_screen_frame.size.height; + + if (FRAME_INITIAL_P (f) || !FRAME_NS_P (f)) + return Qnil; + + CHECK_TYPE_RANGED_INTEGER (int, x); + CHECK_TYPE_RANGED_INTEGER (int, y); + + mouse_x = screen_frame.origin.x + XINT (x); + + if (screen == primary_screen) + mouse_y = screen_frame.origin.y + XINT (y); + else + mouse_y = (primary_screen_height - screen_frame.size.height + - screen_frame.origin.y) + XINT (y); + + CGPoint mouse_pos = CGPointMake(mouse_x, mouse_y); + CGWarpMouseCursorPosition (mouse_pos); + + return Qnil; +} + /* ========================================================================== Class implementations @@ -3254,6 +3292,7 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename defsubr (&Sns_frame_edges); defsubr (&Sns_frame_list_z_order); defsubr (&Sns_frame_restack); + defsubr (&Sns_set_mouse_absolute_pixel_position); defsubr (&Sx_display_mm_width); defsubr (&Sx_display_mm_height); defsubr (&Sx_display_screens); diff --git a/src/nsterm.h b/src/nsterm.h index 9285178d19..ac339bf479 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -1087,7 +1087,7 @@ struct x_output ? ([[FRAME_NS_VIEW (f) window] parentWindow].frame.origin.y \ + [[FRAME_NS_VIEW (f) window] parentWindow].frame.size.height \ - FRAME_NS_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f))) \ - : [[[FRAME_NS_VIEW (f) window] screen] frame].size.height) + : [[[NSScreen screens] objectAtIndex: 0] frame].size.height) #define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table) diff --git a/src/nsterm.m b/src/nsterm.m index c22c5a70ba..a7ab73b63e 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2321,14 +2321,14 @@ so some key presses (TAB) are swallowed by the system. */ -------------------------------------------------------------------------- */ { NSTRACE ("frame_set_mouse_pixel_position"); - ns_raise_frame (f); -#if 0 - /* FIXME: this does not work, and what about GNUstep? */ + + /* FIXME: what about GNUstep? */ #ifdef NS_IMPL_COCOA - [FRAME_NS_VIEW (f) lockFocus]; - PSsetmouse ((float)pix_x, (float)pix_y); - [FRAME_NS_VIEW (f) unlockFocus]; -#endif + CGPoint mouse_pos = + CGPointMake(f->left_pos + pix_x, + f->top_pos + pix_y + + FRAME_NS_TITLEBAR_HEIGHT(f) + FRAME_TOOLBAR_HEIGHT(f)); + CGWarpMouseCursorPosition (mouse_pos); #endif } diff --git a/test/lisp/mouse-tests.el b/test/lisp/mouse-tests.el index fffaa2fa53..a8eca28365 100644 --- a/test/lisp/mouse-tests.el +++ b/test/lisp/mouse-tests.el @@ -47,4 +47,13 @@ translate ‘mouse-1’ events into ‘mouse-2’ events." (should-not (mouse--down-1-maybe-follows-link)) (should (equal unread-command-events '((mouse-2 nil 1)))))) +(ert-deftest bug26816-mouse-frame-movement () + "Mouse moves relative to frame." + (skip-unless (display-graphic-p)) + (let ((frame (selected-frame))) + (set-mouse-position frame 0 0) + (should (equal (mouse-position) + (cons frame (cons 0 0)))))) + + ;;; mouse-tests.el ends here commit c969b3997168de2bbe781fbcb08b67b15eddc02d Author: Alan Third Date: Tue May 16 22:36:21 2017 +0100 Show tooltip on correct screen (bug#26905) * src/nsfns.m (compute_tip_xy): Find the correct screen for the tooltip and constrain it to that screen. diff --git a/src/nsfns.m b/src/nsfns.m index cbe0ffb858..04565a99bb 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2760,6 +2760,7 @@ and GNUstep implementations ("distributor-specific release EmacsView *view = FRAME_NS_VIEW (f); struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); NSPoint pt; + NSScreen *screen; /* Start with user-specified or mouse position. */ left = Fcdr (Fassq (Qleft, parms)); @@ -2794,13 +2795,25 @@ and GNUstep implementations ("distributor-specific release - height); } + /* Find the screen that pt is on. */ + for (screen in [NSScreen screens]) +#ifdef NS_IMPL_COCOA + if (CGRectContainsPoint ([screen frame], pt)) +#else + if (pt.x >= screen.frame.origin.x + && pt.x < screen.frame.origin.x + screen.frame.size.width + && pt.y >= screen.frame.origin.y + && pt.y < screen.frame.origin.y + screen.frame.size.height) +#endif + break; + /* Ensure in bounds. (Note, screen origin = lower left.) */ if (INTEGERP (left) || INTEGERP (right)) *root_x = pt.x; - else if (pt.x + XINT (dx) <= 0) - *root_x = 0; /* Can happen for negative dx */ + else if (pt.x + XINT (dx) <= screen.frame.origin.x) + *root_x = screen.frame.origin.x; /* Can happen for negative dx */ else if (pt.x + XINT (dx) + width - <= x_display_pixel_width (FRAME_DISPLAY_INFO (f))) + <= screen.frame.origin.x + screen.frame.size.width) /* It fits to the right of the pointer. */ *root_x = pt.x + XINT (dx); else if (width + XINT (dx) <= pt.x) @@ -2808,20 +2821,20 @@ and GNUstep implementations ("distributor-specific release *root_x = pt.x - width - XINT (dx); else /* Put it left justified on the screen -- it ought to fit that way. */ - *root_x = 0; + *root_x = screen.frame.origin.x; if (INTEGERP (top) || INTEGERP (bottom)) *root_y = pt.y; - else if (pt.y - XINT (dy) - height >= 0) + else if (pt.y - XINT (dy) - height >= screen.frame.origin.y) /* It fits below the pointer. */ *root_y = pt.y - height - XINT (dy); else if (pt.y + XINT (dy) + height - <= x_display_pixel_height (FRAME_DISPLAY_INFO (f))) + <= screen.frame.origin.y + screen.frame.size.height) /* It fits above the pointer */ *root_y = pt.y + XINT (dy); else /* Put it on the top. */ - *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height; + *root_y = screen.frame.origin.y + screen.frame.size.height - height; } commit ee54d2f4e439b4a211c8fb7541ce22bac65bde8f Author: Noam Postavsky Date: Sat May 20 18:09:24 2017 -0400 ; Set transient-mark-mode to let mark-defun tests pass The tests fail when transient-mark-mode is not set since 2017-05-12 "Fix Bug#21072 and rework `mark-defun'". * test/lisp/progmodes/python-tests.el (python-mark-defun-1) (python-mark-defun-2): Bind 'transient-mark-mode' to t. diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 3b75e81afe..9aaae396a6 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -1317,7 +1317,8 @@ class B: class C: '''docstring''' " - (let ((expected-mark-beginning-position + (let ((transient-mark-mode t) + (expected-mark-beginning-position (progn (python-tests-look-at "class A:") (1- (point)))) @@ -1373,7 +1374,8 @@ class B: class C: '''docstring''' " - (let ((expected-mark-beginning-position + (let ((transient-mark-mode t) + (expected-mark-beginning-position (progn (python-tests-look-at "def __init__(self):") (1- (line-beginning-position)))) commit f151eb01418b80d102c767566e93ac332a8bf7c3 Author: Andreas Politz Date: Sat Mar 4 05:58:34 2017 +0100 Don't save unrelated buffers before recompiling directory (Bug#25964) * lisp/emacs-lisp/bytecomp.el (byte-recompile-directory): Only save buffers visiting lisp files under the directory being compiled. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index e716eef10a..6c12e5d8e2 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1659,7 +1659,12 @@ that already has a `.elc' file." (if arg (setq arg (prefix-numeric-value arg))) (if noninteractive nil - (save-some-buffers) + (save-some-buffers + nil (lambda () + (let ((file (buffer-file-name))) + (and file + (string-match-p emacs-lisp-file-regexp file) + (file-in-directory-p file directory))))) (force-mode-line-update)) (with-current-buffer (get-buffer-create byte-compile-log-buffer) (setq default-directory (expand-file-name directory)) commit 848c90e3d43ed7baebab5f2d02d0a9601c6a142b Author: Paul Eggert Date: Sat May 20 13:43:19 2017 -0700 Minor fixes for arity ranges in emacs modules * src/emacs-module.c (module_make_function): Check that arities fit into fixnums, for func-arity’s benefit. (funcall_module): Avoid unnecessary conversion to EMACS_INT. (module_function_arity): Allow arities greater than SHRT_MAX. diff --git a/src/emacs-module.c b/src/emacs-module.c index 99be4a748e..5ab6913595 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -358,8 +358,9 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, if (! (0 <= min_arity && (max_arity < 0 - ? max_arity == emacs_variadic_function - : min_arity <= max_arity))) + ? (min_arity <= MOST_POSITIVE_FIXNUM + && max_arity == emacs_variadic_function) + : min_arity <= max_arity && max_arity <= MOST_POSITIVE_FIXNUM))) xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity)); struct Lisp_Module_Function *envptr = allocate_module_function (); @@ -646,12 +647,11 @@ Lisp_Object funcall_module (const struct Lisp_Module_Function *const envptr, ptrdiff_t nargs, Lisp_Object *arglist) { - EMACS_INT len = nargs; eassume (0 <= envptr->min_arity); - if (! (envptr->min_arity <= len - && len <= (envptr->max_arity < 0 ? PTRDIFF_MAX : envptr->max_arity))) + if (! (envptr->min_arity <= nargs + && (envptr->max_arity < 0 || nargs <= envptr->max_arity))) xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr), - make_number (len)); + make_number (nargs)); emacs_env pub; struct emacs_env_private priv; @@ -663,12 +663,12 @@ funcall_module (const struct Lisp_Module_Function *const envptr, args = (emacs_value *) arglist; else { - args = SAFE_ALLOCA (len * sizeof *args); - for (ptrdiff_t i = 0; i < len; i++) + args = SAFE_ALLOCA (nargs * sizeof *args); + for (ptrdiff_t i = 0; i < nargs; i++) args[i] = lisp_to_value (arglist[i]); } - emacs_value ret = envptr->subr (&pub, len, args, envptr->data); + emacs_value ret = envptr->subr (&pub, nargs, args, envptr->data); SAFE_FREE (); eassert (&priv == pub.private_members); @@ -700,8 +700,8 @@ funcall_module (const struct Lisp_Module_Function *const envptr, Lisp_Object module_function_arity (const struct Lisp_Module_Function *const function) { - const short minargs = function->min_arity; - const short maxargs = function->max_arity; + ptrdiff_t minargs = function->min_arity; + ptrdiff_t maxargs = function->max_arity; return Fcons (make_number (minargs), maxargs == MANY ? Qmany : make_number (maxargs)); } commit 31fded0370c3aa6d2c4370cae21cdb7475873483 Author: Philipp Stephani Date: Sat May 13 16:29:40 2017 +0200 Reimplement module functions Instead of a lambda, create a new type containing all data required to call the function, and support it in the evaluator. Because this type now also needs to store the function documentation, it is too big for Lisp_Misc; use a pseudovector instead. That also has the nice benefit that we don't have to add special support to the garbage collector. Since the new type is user-visible, give it a predicate. Now we can easily support 'help-function-args' and 'func-arity'; add unit tests for these. * src/lisp.h (allocate_module_function, MODULE_FUNCTIONP) (XMODULE_FUNCTION): New pseudovector type 'module function'. * src/eval.c (FUNCTIONP): Also treat module functions as functions. (funcall_lambda, Ffuncall, eval_sub): Add support for calling module functions. (Ffunc_arity): Add support for detecting the arity of module functions. * src/emacs-module.c (module_make_function): Adapt to new structure. Return module function object directly instead of wrapping it in a lambda; remove FIXME. (funcall_module): New function to call module functions. Replaces `internal--module-call' and is called directly from eval.c. (syms_of_module): Remove internal helper function, which is no longer needed. (module_function_arity): New helper function. * src/data.c (Ftype_of): Adapt to new implementation. (Fmodule_function_p, syms_of_data): New user-visible function. Now that module functions are first-class objects, they deserve a predicate. Define it even if not compiled with --enable-modules so that Lisp code doesn't have to check for the function's existence. * src/doc.c (Fdocumentation): Support module functions. * src/print.c (print_object): Adapt to new implementation. * src/alloc.c (mark_object): Specialized garbage collector support is no longer needed. * lisp/help.el (help-function-arglist): Support module functions. While there, simplify the arity calculation by using `func-arity', which does the right thing for all kinds of functions. * test/data/emacs-module/mod-test.c: Amend docstring so we can test the argument list. * test/src/emacs-module-tests.el (mod-test-sum-docstring): Adapt to new docstring. (mod-test-non-local-exit-signal-test): Because `internal--module-call' is gone, the backtrace has changed and no longer leaks the implementation. (module--func-arity): New test for `func-arity'. (module--help-function-arglist): New test for `help-function-arglist'. diff --git a/etc/NEWS b/etc/NEWS index 2a4b7014d4..eeb7c773ac 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -946,6 +946,12 @@ instead of its first. renamed to 'lread--old-style-backquotes'. No user code should use this variable. ++++ +** Module functions are now implemented slightly differently; in +particular, the function 'internal--module-call' has been removed. +Code that depends on undocumented internals of the module system might +break. + * Lisp Changes in Emacs 26.1 diff --git a/lisp/help.el b/lisp/help.el index 26be3b0e07..361ab2a01e 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1430,7 +1430,7 @@ the same names as used in the original source code, when possible." ((eq (car-safe def) 'lambda) (nth 1 def)) ((eq (car-safe def) 'closure) (nth 2 def)) ((or (and (byte-code-function-p def) (integerp (aref def 0))) - (subrp def)) + (subrp def) (module-function-p def)) (or (when preserve-names (let* ((doc (condition-case nil (documentation def) (error nil))) (docargs (if doc (car (help-split-fundoc doc nil)))) @@ -1446,25 +1446,18 @@ the same names as used in the original source code, when possible." (not (string-match "\\." name))))) (setq valid nil))) (when valid arglist))) - (let* ((args-desc (if (not (subrp def)) - (aref def 0) - (let ((a (subr-arity def))) - (logior (car a) - (if (numberp (cdr a)) - (lsh (cdr a) 8) - (lsh 1 7)))))) - (max (lsh args-desc -8)) - (min (logand args-desc 127)) - (rest (logand args-desc 128)) + (let* ((arity (func-arity def)) + (max (cdr arity)) + (min (car arity)) (arglist ())) (dotimes (i min) (push (intern (concat "arg" (number-to-string (1+ i)))) arglist)) - (when (> max min) + (when (and (integerp max) (> max min)) (push '&optional arglist) (dotimes (i (- max min)) (push (intern (concat "arg" (number-to-string (+ 1 i min)))) arglist))) - (unless (zerop rest) (push '&rest arglist) (push 'rest arglist)) + (unless (integerp max) (push '&rest arglist) (push 'rest arglist)) (nreverse arglist)))) ((and (autoloadp def) (not (eq (nth 4 def) 'keymap))) "[Arg list not available until function definition is loaded.]") diff --git a/src/alloc.c b/src/alloc.c index faa14eebb3..b473ebd7de 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3942,13 +3942,6 @@ make_user_ptr (void (*finalizer) (void *), void *p) uptr->p = p; return obj; } - -/* Create a new module function environment object. */ -Lisp_Object -make_module_function (void) -{ - return allocate_misc (Lisp_Misc_Module_Function); -} #endif static void @@ -6640,7 +6633,6 @@ mark_object (Lisp_Object arg) #ifdef HAVE_MODULES case Lisp_Misc_User_Ptr: - case Lisp_Misc_Module_Function: XMISCANY (obj)->gcmarkbit = true; break; #endif diff --git a/src/data.c b/src/data.c index 4242b90e62..25859105ee 100644 --- a/src/data.c +++ b/src/data.c @@ -233,8 +233,6 @@ for example, (type-of 1) returns `integer'. */) case Lisp_Misc_Finalizer: return Qfinalizer; #ifdef HAVE_MODULES - case Lisp_Misc_Module_Function: - return Qmodule_function; case Lisp_Misc_User_Ptr: return Quser_ptr; #endif @@ -278,6 +276,8 @@ for example, (type-of 1) returns `integer'. */) else return t; } + case PVEC_MODULE_FUNCTION: + return Qmodule_function; /* "Impossible" cases. */ case PVEC_XWIDGET: case PVEC_OTHER: @@ -494,6 +494,14 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p, return Qnil; } +DEFUN ("module-function-p", Fmodule_function_p, Smodule_function_p, 1, 1, NULL, + doc: /* Return t if OBJECT is a function loaded from a dynamic module. */ + attributes: const) + (Lisp_Object object) +{ + return MODULE_FUNCTIONP (object) ? Qt : Qnil; +} + DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, doc: /* Return t if OBJECT is a character or a string. */ attributes: const) @@ -3793,6 +3801,7 @@ syms_of_data (void) defsubr (&Smarkerp); defsubr (&Ssubrp); defsubr (&Sbyte_code_function_p); + defsubr (&Smodule_function_p); defsubr (&Schar_or_string_p); defsubr (&Sthreadp); defsubr (&Smutexp); diff --git a/src/doc.c b/src/doc.c index dd674e3bc0..345e18b918 100644 --- a/src/doc.c +++ b/src/doc.c @@ -340,6 +340,8 @@ string is passed through `substitute-command-keys'. */) fun = XCDR (fun); if (SUBRP (fun)) doc = make_number (XSUBR (fun)->doc); + else if (MODULE_FUNCTIONP (fun)) + doc = XMODULE_FUNCTION (fun)->documentation; else if (COMPILEDP (fun)) { if (PVSIZE (fun) <= COMPILED_DOC_STRING) diff --git a/src/emacs-module.c b/src/emacs-module.c index 0bc1b6c384..99be4a748e 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -362,30 +362,24 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, : min_arity <= max_arity))) xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity)); - Lisp_Object envobj = make_module_function (); - struct Lisp_Module_Function *envptr = XMODULE_FUNCTION (envobj); + struct Lisp_Module_Function *envptr = allocate_module_function (); envptr->min_arity = min_arity; envptr->max_arity = max_arity; envptr->subr = subr; envptr->data = data; - Lisp_Object doc = Qnil; if (documentation) { AUTO_STRING (unibyte_doc, documentation); - doc = code_convert_string_norecord (unibyte_doc, Qutf_8, false); + envptr->documentation = + code_convert_string_norecord (unibyte_doc, Qutf_8, false); } - /* FIXME: Use a bytecompiled object, or even better a subr. */ - Lisp_Object ret = list4 (Qlambda, - list2 (Qand_rest, Qargs), - doc, - list4 (Qapply, - list2 (Qfunction, Qinternal__module_call), - envobj, - Qargs)); + Lisp_Object envobj; + XSET_MODULE_FUNCTION (envobj, envptr); + eassert (MODULE_FUNCTIONP (envobj)); - return lisp_to_value (ret); + return lisp_to_value (envobj); } static emacs_value @@ -648,17 +642,11 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0, return Qt; } -DEFUN ("internal--module-call", Finternal_module_call, Sinternal_module_call, 1, MANY, 0, - doc: /* Internal function to call a module function. -ENVOBJ is a save pointer to a module_fun_env structure. -ARGLIST is a list of arguments passed to SUBRPTR. -usage: (module-call ENVOBJ &rest ARGLIST) */) - (ptrdiff_t nargs, Lisp_Object *arglist) +Lisp_Object +funcall_module (const struct Lisp_Module_Function *const envptr, + ptrdiff_t nargs, Lisp_Object *arglist) { - Lisp_Object envobj = arglist[0]; - CHECK_TYPE (MODULE_FUNCTIONP (envobj), Qmodule_function_p, envobj); - struct Lisp_Module_Function *envptr = XMODULE_FUNCTION (envobj); - EMACS_INT len = nargs - 1; + EMACS_INT len = nargs; eassume (0 <= envptr->min_arity); if (! (envptr->min_arity <= len && len <= (envptr->max_arity < 0 ? PTRDIFF_MAX : envptr->max_arity))) @@ -672,12 +660,12 @@ usage: (module-call ENVOBJ &rest ARGLIST) */) USE_SAFE_ALLOCA; emacs_value *args; if (plain_values) - args = (emacs_value *) arglist + 1; + args = (emacs_value *) arglist; else { args = SAFE_ALLOCA (len * sizeof *args); for (ptrdiff_t i = 0; i < len; i++) - args[i] = lisp_to_value (arglist[i + 1]); + args[i] = lisp_to_value (arglist[i]); } emacs_value ret = envptr->subr (&pub, len, args, envptr->data); @@ -709,6 +697,15 @@ usage: (module-call ENVOBJ &rest ARGLIST) */) } } +Lisp_Object +module_function_arity (const struct Lisp_Module_Function *const function) +{ + const short minargs = function->min_arity; + const short maxargs = function->max_arity; + return Fcons (make_number (minargs), + maxargs == MANY ? Qmany : make_number (maxargs)); +} + /* Helper functions. */ @@ -1025,7 +1022,4 @@ syms_of_module (void) DEFSYM (Qmodule_function_p, "module-function-p"); defsubr (&Smodule_load); - - DEFSYM (Qinternal__module_call, "internal--module-call"); - defsubr (&Sinternal_module_call); } diff --git a/src/eval.c b/src/eval.c index 98d25cc4fe..f472efad52 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2261,7 +2261,7 @@ eval_sub (Lisp_Object form) } } } - else if (COMPILEDP (fun)) + else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun)) return apply_lambda (fun, original_args, count); else { @@ -2687,7 +2687,7 @@ FUNCTIONP (Lisp_Object object) if (SUBRP (object)) return XSUBR (object)->max_args != UNEVALLED; - else if (COMPILEDP (object)) + else if (COMPILEDP (object) || MODULE_FUNCTIONP (object)) return true; else if (CONSP (object)) { @@ -2742,7 +2742,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) if (SUBRP (fun)) val = funcall_subr (XSUBR (fun), numargs, args + 1); - else if (COMPILEDP (fun)) + else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun)) val = funcall_lambda (fun, numargs, args + 1); else { @@ -2892,7 +2892,8 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count) /* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR and return the result of evaluation. - FUN must be either a lambda-expression or a compiled-code object. */ + FUN must be either a lambda-expression, a compiled-code object, + or a module function. */ static Lisp_Object funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, @@ -2949,6 +2950,10 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, } lexenv = Qnil; } +#ifdef HAVE_MODULES + else if (MODULE_FUNCTIONP (fun)) + return funcall_module (XMODULE_FUNCTION (fun), nargs, arg_vector); +#endif else emacs_abort (); @@ -3060,6 +3065,10 @@ function with `&rest' args, or `unevalled' for a special form. */) result = Fsubr_arity (function); else if (COMPILEDP (function)) result = lambda_arity (function); +#ifdef HAVE_MODULES + else if (MODULE_FUNCTIONP (function)) + result = module_function_arity (XMODULE_FUNCTION (function)); +#endif else { if (NILP (function)) diff --git a/src/lisp.h b/src/lisp.h index de3a548cb6..ec8a8b1c09 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -464,7 +464,6 @@ enum Lisp_Misc_Type Lisp_Misc_Save_Value, Lisp_Misc_Finalizer, #ifdef HAVE_MODULES - Lisp_Misc_Module_Function, Lisp_Misc_User_Ptr, #endif /* Currently floats are not a misc type, @@ -885,6 +884,7 @@ enum pvec_type PVEC_THREAD, PVEC_MUTEX, PVEC_CONDVAR, + PVEC_MODULE_FUNCTION, /* These should be last, check internal_equal to see why. */ PVEC_COMPILED, @@ -2386,28 +2386,6 @@ struct Lisp_User_Ptr void (*finalizer) (void *); void *p; }; - -#include "emacs-module.h" - -/* Function prototype for the module Lisp functions. */ -typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t, - emacs_value [], void *); - -/* Function environments. */ - -/* A function environment is an auxiliary structure used by - `module_make_function' to store information about a module - function. It is stored in a save pointer and retrieved by - `internal--module-call'. Its members correspond to the arguments - given to `module_make_function'. */ - -struct Lisp_Module_Function -{ - struct Lisp_Misc_Any base; - ptrdiff_t min_arity, max_arity; - emacs_subr subr; - void *data; -}; #endif /* A finalizer sentinel. */ @@ -2460,7 +2438,6 @@ union Lisp_Misc struct Lisp_Finalizer u_finalizer; #ifdef HAVE_MODULES struct Lisp_User_Ptr u_user_ptr; - struct Lisp_Module_Function u_module_function; #endif }; @@ -2509,19 +2486,6 @@ XUSER_PTR (Lisp_Object a) eassert (USER_PTRP (a)); return XUNTAG (a, Lisp_Misc); } - -INLINE bool -MODULE_FUNCTIONP (Lisp_Object o) -{ - return MISCP (o) && XMISCTYPE (o) == Lisp_Misc_Module_Function; -} - -INLINE struct Lisp_Module_Function * -XMODULE_FUNCTION (Lisp_Object o) -{ - eassert (MODULE_FUNCTIONP (o)); - return XUNTAG (o, Lisp_Misc); -} #endif @@ -3923,12 +3887,66 @@ extern void get_backtrace (Lisp_Object array); Lisp_Object backtrace_top_function (void); extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); +#include "emacs-module.h" + +/* Function prototype for the module Lisp functions. */ +typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t, + emacs_value [], void *); + +/* Function environments. */ + +/* A function environment is an auxiliary structure used by + `module_make_function' to store information about a module + function. It is stored in a pseudovector. Its members correspond + to the arguments given to `module_make_function'. */ + +struct Lisp_Module_Function +{ + struct vectorlike_header header; + + /* Fields traced by GC; these must come first. */ + Lisp_Object documentation; + + /* Fields ignored by GC. */ + ptrdiff_t min_arity, max_arity; + emacs_subr subr; + void *data; +}; + +INLINE struct Lisp_Module_Function * +allocate_module_function (void) +{ + return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function, + /* Name of the first field to be + ignored by GC. */ + min_arity, + PVEC_MODULE_FUNCTION); +} + +INLINE bool +MODULE_FUNCTIONP (Lisp_Object o) +{ + return PSEUDOVECTORP (o, PVEC_MODULE_FUNCTION); +} + +INLINE struct Lisp_Module_Function * +XMODULE_FUNCTION (Lisp_Object o) +{ + eassert (MODULE_FUNCTIONP (o)); + return XUNTAG (o, Lisp_Vectorlike); +} + +#define XSET_MODULE_FUNCTION(var, ptr) \ + (XSETPSEUDOVECTOR (var, ptr, PVEC_MODULE_FUNCTION)) + #ifdef HAVE_MODULES /* Defined in alloc.c. */ extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); -extern Lisp_Object make_module_function (void); /* Defined in emacs-module.c. */ +extern Lisp_Object funcall_module (const struct Lisp_Module_Function *, + ptrdiff_t, Lisp_Object *); +extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *); extern Lisp_Object module_format_fun_env (const struct Lisp_Module_Function *); extern void syms_of_module (void); #endif diff --git a/src/print.c b/src/print.c index 7e411a80c8..be2e16a749 100644 --- a/src/print.c +++ b/src/print.c @@ -2051,6 +2051,13 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) } break; +#ifdef HAVE_MODULES + case PVEC_MODULE_FUNCTION: + print_string (module_format_fun_env (XMODULE_FUNCTION (obj)), + printcharfun); + break; +#endif + case PVEC_OTHER: case PVEC_FREE: emacs_abort (); @@ -2103,11 +2110,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) printchar ('>', printcharfun); break; } - - case Lisp_Misc_Module_Function: - print_string (module_format_fun_env (XMODULE_FUNCTION (obj)), - printcharfun); - break; #endif case Lisp_Misc_Finalizer: diff --git a/test/data/emacs-module/mod-test.c b/test/data/emacs-module/mod-test.c index 50be8620bd..309179d150 100644 --- a/test/data/emacs-module/mod-test.c +++ b/test/data/emacs-module/mod-test.c @@ -249,7 +249,7 @@ emacs_module_init (struct emacs_runtime *ert) env->make_function (env, amin, amax, csym, doc, data)) DEFUN ("mod-test-return-t", Fmod_test_return_t, 1, 1, NULL, NULL); - DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B", NULL); + DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)", NULL); DEFUN ("mod-test-signal", Fmod_test_signal, 0, 0, NULL, NULL); DEFUN ("mod-test-throw", Fmod_test_throw, 0, 0, NULL, NULL); DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall, diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el index 0f4bfae00a..5e78aebf7c 100644 --- a/test/src/emacs-module-tests.el +++ b/test/src/emacs-module-tests.el @@ -57,33 +57,22 @@ :type 'overflow-error)) (ert-deftest mod-test-sum-docstring () - (should (string= (documentation 'mod-test-sum) "Return A + B"))) + (should (string= (documentation 'mod-test-sum) "Return A + B\n\n(fn a b)"))) (ert-deftest module-function-object () "Extract and test the implementation of a module function. This test needs to be changed whenever the implementation changes." (let ((func (symbol-function #'mod-test-sum))) - (should (consp func)) - (should (equal (length func) 4)) - (should (equal (nth 0 func) 'lambda)) - (should (equal (nth 1 func) '(&rest args))) - (should (equal (nth 2 func) "Return A + B")) - (let ((body (nth 3 func))) - (should (consp body)) - (should (equal (length body) 4)) - (should (equal (nth 0 body) #'apply)) - (should (equal (nth 1 body) '#'internal--module-call)) - (should (equal (nth 3 body) 'args)) - (let ((obj (nth 2 body))) - (should (equal (type-of obj) 'module-function)) - (should (string-match-p - (rx "#") - (prin1-to-string obj))))))) + (should (module-function-p func)) + (should (equal (type-of func) 'module-function)) + (should (string-match-p + (rx bos "#" eos) + (prin1-to-string func))))) ;; ;; Non-local exists (throw, signal). @@ -101,9 +90,7 @@ changes." (mod-test-signal))) (should (equal debugger-args '(error (error . 56)))) (should (string-match-p - (rx bol " internal--module-call(" (+ nonl) ?\) ?\n - " apply(internal--module-call " (+ nonl) ?\) ?\n - " mod-test-signal()" eol) + (rx bol " mod-test-signal()" eol) backtrace)))) (ert-deftest mod-test-non-local-exit-throw-test () @@ -172,3 +159,19 @@ changes." (should (eq (mod-test-vector-fill v-test e) t)) (should (eq (mod-test-vector-eq v-test e) eq-ref)))))) + +(ert-deftest module--func-arity () + (should (equal (func-arity #'mod-test-return-t) '(1 . 1))) + (should (equal (func-arity #'mod-test-sum) '(2 . 2)))) + +(ert-deftest module--help-function-arglist () + (should (equal (help-function-arglist #'mod-test-return-t :preserve-names) + '(arg1))) + (should (equal (help-function-arglist #'mod-test-return-t) + '(arg1))) + (should (equal (help-function-arglist #'mod-test-sum :preserve-names) + '(a b))) + (should (equal (help-function-arglist #'mod-test-sum) + '(arg1 arg2)))) + +;;; emacs-module-tests.el ends here commit 6c7bf039e9c2e6daf548a95204740eeaf4c61abd Author: Eli Zaretskii Date: Sat May 20 14:53:06 2017 +0300 Avoid crashes in GC due to unescaped characters warning * src/lread.c (load_warn_unescaped_character_literals): Don't cons Lisp objects from stack-based variables. (Bug#26961) diff --git a/src/lread.c b/src/lread.c index 5e737d690c..9e2168e7db 100644 --- a/src/lread.c +++ b/src/lread.c @@ -960,10 +960,10 @@ load_warn_unescaped_character_literals (Lisp_Object file) { if (NILP (Vlread_unescaped_character_literals)) return; CHECK_CONS (Vlread_unescaped_character_literals); - AUTO_STRING (format, - "Loading `%s': unescaped character literals %s detected!"); - AUTO_STRING (separator, ", "); - AUTO_STRING (inner_format, "`?%c'"); + Lisp_Object format = + build_string ("Loading `%s': unescaped character literals %s detected!"); + Lisp_Object separator = build_string (", "); + Lisp_Object inner_format = build_string ("`?%c'"); CALLN (Fmessage, format, file, Fmapconcat (list3 (Qlambda, list1 (Qchar), commit 021430f4b48ceb43a443fe805cfe0b21e7829760 Author: Charles A. Roelli Date: Sat May 20 14:41:53 2017 +0300 New commands: find-library-other-window, find-library-other-frame * lisp/emacs-lisp/find-func.el (find-library-other-window) (find-library-other-frame): New commands to complement the existing 'find-library' command. (Bug#26712) (read-library-name): New function to read a library name. * etc/NEWS: Mention 'find-library-other-window' and 'find-library-other-frame'. diff --git a/etc/NEWS b/etc/NEWS index aa579b11c7..2a4b7014d4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -356,6 +356,9 @@ use the local Emacs to edit remote files via Tramp. See the node ** The new variable 'eval-expression-print-maximum-character' prevents large integers from being displayed as characters. +** Two new commands for finding the source code of Emacs Lisp +libraries: 'find-library-other-window' and 'find-library-other-frame'. + * Editing Changes in Emacs 26.1 diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index d0acc14775..9b98f05ae8 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -271,43 +271,65 @@ TYPE should be nil to find a function, or `defvar' to find a variable." (cons (current-buffer) (match-beginning 0)))) ;;;###autoload -(defun find-library (library &optional other-window) +(defun find-library (library) "Find the Emacs Lisp source of LIBRARY. -LIBRARY should be a string (the name of the library). If the -optional OTHER-WINDOW argument (i.e., the command argument) is -specified, pop to a different window before displaying the -buffer." - (interactive - (let* ((dirs (or find-function-source-path load-path)) - (suffixes (find-library-suffixes)) - (table (apply-partially 'locate-file-completion-table - dirs suffixes)) - (def (if (eq (function-called-at-point) 'require) - ;; `function-called-at-point' may return 'require - ;; with `point' anywhere on this line. So wrap the - ;; `save-excursion' below in a `condition-case' to - ;; avoid reporting a scan-error here. - (condition-case nil - (save-excursion - (backward-up-list) - (forward-char) - (forward-sexp 2) - (thing-at-point 'symbol)) - (error nil)) - (thing-at-point 'symbol)))) - (when (and def (not (test-completion def table))) - (setq def nil)) - (list - (completing-read (if def - (format "Library name (default %s): " def) - "Library name: ") - table nil nil nil nil def) - current-prefix-arg))) + +Interactively, prompt for LIBRARY using the one at or near point." + (interactive (list (read-library-name))) + (prog1 + (switch-to-buffer (find-file-noselect (find-library-name library))) + (run-hooks 'find-function-after-hook))) + +(defun read-library-name () + "Read and return a library name, defaulting to the one near point. + +A library name is the filename of an Emacs Lisp library located +in a directory under `load-path' (or `find-function-source-path', +if non-nil)." + (let* ((dirs (or find-function-source-path load-path)) + (suffixes (find-library-suffixes)) + (table (apply-partially 'locate-file-completion-table + dirs suffixes)) + (def (if (eq (function-called-at-point) 'require) + ;; `function-called-at-point' may return 'require + ;; with `point' anywhere on this line. So wrap the + ;; `save-excursion' below in a `condition-case' to + ;; avoid reporting a scan-error here. + (condition-case nil + (save-excursion + (backward-up-list) + (forward-char) + (forward-sexp 2) + (thing-at-point 'symbol)) + (error nil)) + (thing-at-point 'symbol)))) + (when (and def (not (test-completion def table))) + (setq def nil)) + (completing-read (if def + (format "Library name (default %s): " def) + "Library name: ") + table nil nil nil nil def))) + +;;;###autoload +(defun find-library-other-window (library) + "Find the Emacs Lisp source of LIBRARY in another window. + +See `find-library' for more details." + (interactive (list (read-library-name))) + (prog1 + (switch-to-buffer-other-window (find-file-noselect + (find-library-name library))) + (run-hooks 'find-function-after-hook))) + +;;;###autoload +(defun find-library-other-frame (library) + "Find the Emacs Lisp source of LIBRARY in another frame. + +See `find-library' for more details." + (interactive (list (read-library-name))) (prog1 - (funcall (if other-window - 'pop-to-buffer - 'pop-to-buffer-same-window) - (find-file-noselect (find-library-name library))) + (switch-to-buffer-other-frame (find-file-noselect + (find-library-name library))) (run-hooks 'find-function-after-hook))) ;;;###autoload commit 1cbbecee66617a232d6ed361f842128564599e70 Author: Eli Zaretskii Date: Sat May 20 10:32:58 2017 +0300 Fix automatic hscrolling of only the current line * src/xdisp.c (display_line): When hscrolling only the current line, increment iterator's first_visible_x and last_visible_x values to account for the hscroll. This propagates the hscroll effect on the iterator geometry all the way down to the subroutines called by display_line, and avoids scrolling bugs under large hscroll values. (Bug#26994) diff --git a/src/xdisp.c b/src/xdisp.c index 96bc1a5e03..c0e821a934 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -20671,8 +20671,11 @@ display_line (struct it *it, int cursor_vpos) ptrdiff_t min_pos = ZV + 1, max_pos = 0; ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; bool pending_handle_line_prefix = false; + bool hscroll_this_line = (cursor_vpos >= 0 && it->vpos == cursor_vpos + && hscrolling_current_line_p (it->w)); int first_visible_x = it->first_visible_x; int last_visible_x = it->last_visible_x; + int x_incr = 0; /* We always start displaying at hpos zero even if hscrolled. */ eassert (it->hpos == 0 && it->current_x == 0); @@ -20704,25 +20707,23 @@ display_line (struct it *it, int cursor_vpos) /* If we are going to display the cursor's line, account for the hscroll of that line. */ - if (cursor_vpos >= 0 && it->vpos == cursor_vpos - && hscrolling_current_line_p (it->w)) - { - int x_incr = - window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f); - - first_visible_x += x_incr; - last_visible_x += x_incr; - } + if (hscroll_this_line) + x_incr = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f); /* Move over display elements that are not visible because we are hscrolled. This may stop at an x-position < first_visible_x if the first glyph is partially visible or if we hit a line end. */ - if (it->current_x < first_visible_x) + if (it->current_x < it->first_visible_x + x_incr) { enum move_it_result move_result; this_line_min_pos = row->start.pos; - move_result = move_it_in_display_line_to (it, ZV, first_visible_x, + if (hscroll_this_line) + { + it->first_visible_x += x_incr; + it->last_visible_x += x_incr; + } + move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x, MOVE_TO_POS | MOVE_TO_X); /* If we are under a large hscroll, move_it_in_display_line_to could hit the end of the line without reaching @@ -20730,10 +20731,10 @@ display_line (struct it *it, int cursor_vpos) especially important on a TTY, where we will call extend_face_to_end_of_line, which needs to know how many blank glyphs to produce. */ - if (it->current_x < first_visible_x + if (it->current_x < it->first_visible_x && (move_result == MOVE_NEWLINE_OR_CR || move_result == MOVE_POS_MATCH_OR_ZV)) - it->current_x = first_visible_x; + it->current_x = it->first_visible_x; /* Record the smallest positions seen while we moved over display elements that are not visible. This is needed by @@ -20927,7 +20928,7 @@ display_line (struct it *it, int cursor_vpos) if (/* Not a newline. */ nglyphs > 0 /* Glyphs produced fit entirely in the line. */ - && it->current_x < last_visible_x) + && it->current_x < it->last_visible_x) { it->hpos += nglyphs; row->ascent = max (row->ascent, it->max_ascent); @@ -20937,13 +20938,13 @@ display_line (struct it *it, int cursor_vpos) it->max_phys_ascent + it->max_phys_descent); row->extra_line_spacing = max (row->extra_line_spacing, it->max_extra_line_spacing); - if (it->current_x - it->pixel_width < first_visible_x + if (it->current_x - it->pixel_width < it->first_visible_x /* In R2L rows, we arrange in extend_face_to_end_of_line to add a right offset to the line, by a suitable change to the stretch glyph that is the leftmost glyph of the line. */ && !row->reversed_p) - row->x = x - first_visible_x; + row->x = x - it->first_visible_x; /* Record the maximum and minimum buffer positions seen so far in glyphs that will be displayed by this row. */ if (it->bidi_p) @@ -20968,9 +20969,9 @@ display_line (struct it *it, int cursor_vpos) if (/* Lines are continued. */ it->line_wrap != TRUNCATE && (/* Glyph doesn't fit on the line. */ - new_x > last_visible_x + new_x > it->last_visible_x /* Or it fits exactly on a window system frame. */ - || (new_x == last_visible_x + || (new_x == it->last_visible_x && FRAME_WINDOW_P (it->f) && (row->reversed_p ? WINDOW_LEFT_FRINGE_WIDTH (it->w) @@ -20979,7 +20980,7 @@ display_line (struct it *it, int cursor_vpos) /* End of a continued line. */ if (it->hpos == 0 - || (new_x == last_visible_x + || (new_x == it->last_visible_x && FRAME_WINDOW_P (it->f) && (row->reversed_p ? WINDOW_LEFT_FRINGE_WIDTH (it->w) @@ -21122,10 +21123,10 @@ display_line (struct it *it, int cursor_vpos) ? WINDOW_LEFT_FRINGE_WIDTH (it->w) : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0) produce_special_glyphs (it, IT_CONTINUATION); - it->continuation_lines_width += last_visible_x; + it->continuation_lines_width += it->last_visible_x; row->ends_in_middle_of_char_p = true; row->continued_p = true; - glyph->pixel_width = last_visible_x - x; + glyph->pixel_width = it->last_visible_x - x; it->starts_in_middle_of_char_p = true; if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0) @@ -21169,7 +21170,7 @@ display_line (struct it *it, int cursor_vpos) break; } - else if (new_x > first_visible_x) + else if (new_x > it->first_visible_x) { /* Increment number of glyphs actually displayed. */ ++it->hpos; @@ -21180,14 +21181,14 @@ display_line (struct it *it, int cursor_vpos) if (it->bidi_p) RECORD_MAX_MIN_POS (it); - if (x < first_visible_x && !row->reversed_p) + if (x < it->first_visible_x && !row->reversed_p) /* Glyph is partially visible, i.e. row starts at negative X position. Don't do that in R2L rows, where we arrange to add a right offset to the line in extend_face_to_end_of_line, by a suitable change to the stretch glyph that is the leftmost glyph of the line. */ - row->x = x - first_visible_x; + row->x = x - it->first_visible_x; /* When the last glyph of an R2L row only fits partially on the line, we need to set row->x to a negative offset, so that the leftmost glyph is @@ -21195,12 +21196,12 @@ display_line (struct it *it, int cursor_vpos) going to produce the truncation glyph, this will be taken care of in produce_special_glyphs. */ if (row->reversed_p - && new_x > last_visible_x + && new_x > it->last_visible_x && !(it->line_wrap == TRUNCATE && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)) { eassert (FRAME_WINDOW_P (it->f)); - row->x = last_visible_x - new_x; + row->x = it->last_visible_x - new_x; } } else @@ -21210,7 +21211,7 @@ display_line (struct it *it, int cursor_vpos) move_it_in_display_line at the start of this function, unless the text display area of the window is empty. */ - eassert (first_visible_x <= last_visible_x); + eassert (it->first_visible_x <= it->last_visible_x); } } /* Even if this display element produced no glyphs at all, @@ -21279,8 +21280,8 @@ display_line (struct it *it, int cursor_vpos) ? WINDOW_LEFT_FRINGE_WIDTH (it->w) : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) || it->what == IT_IMAGE)) - ? (it->current_x >= last_visible_x) - : (it->current_x > last_visible_x))) + ? (it->current_x >= it->last_visible_x) + : (it->current_x > it->last_visible_x))) { /* Maybe add truncation glyphs. */ if (!FRAME_WINDOW_P (it->f) @@ -21314,7 +21315,7 @@ display_line (struct it *it, int cursor_vpos) /* produce_special_glyphs overwrites the last glyph, so we don't want that if we want to keep that last glyph, which means it's an image. */ - if (it->current_x > last_visible_x) + if (it->current_x > it->last_visible_x) { it->current_x = x_before; if (!FRAME_WINDOW_P (it->f)) @@ -21375,7 +21376,7 @@ display_line (struct it *it, int cursor_vpos) /* If line is not empty and hscrolled, maybe insert truncation glyphs at the left window margin. */ - if (first_visible_x + if (it->first_visible_x && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) { if (!FRAME_WINDOW_P (it->f) @@ -21503,6 +21504,13 @@ display_line (struct it *it, int cursor_vpos) row to be used. */ it->current_x = it->hpos = 0; it->current_y += row->height; + /* Restore the first and last visible X if we adjusted them for + current-line hscrolling. */ + if (hscroll_this_line) + { + it->first_visible_x = first_visible_x; + it->last_visible_x = last_visible_x; + } SET_TEXT_POS (it->eol_pos, 0, 0); ++it->vpos; ++it->glyph_row; commit 7d00410af69b3cbbf0e8fc9765f3bf9f5616286d Author: Paul Eggert Date: Fri May 19 16:15:07 2017 -0700 Add handlerlist assertion to module code * src/emacs-module.c (module_reset_handlerlist): Check handlerlist. Suggested by Philipp Stephani in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00521.html diff --git a/src/emacs-module.c b/src/emacs-module.c index 5aa8a88174..0bc1b6c384 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -918,10 +918,12 @@ finalize_environment (struct emacs_env_private *env) /* Must be called after setting up a handler immediately before returning from the function. See the comments in lisp.h and the code in eval.c for details. The macros below arrange for this - function to be called automatically. DUMMY is ignored. */ + function to be called automatically. PHANDLERLIST points to a word + containing the handler list, for sanity checking. */ static void -module_reset_handlerlist (struct handler *const *dummy) +module_reset_handlerlist (struct handler *const *phandlerlist) { + eassert (handlerlist == *phandlerlist); handlerlist = handlerlist->next; } commit a5acb3701a7b4ab8b82aede308d28a47a383ae9c Author: Paul Eggert Date: Fri May 19 16:05:31 2017 -0700 Port --enable-gcc-warnings to clang 3.9.1 * configure.ac (WERROR_CFLAGS): Omit -Wmissing-braces for Clang, to shut off a false alarm. Problem reportd by Philipp Stephani in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00521.html diff --git a/configure.ac b/configure.ac index 03542a6b1c..12e44d949c 100644 --- a/configure.ac +++ b/configure.ac @@ -964,6 +964,7 @@ AS_IF([test $gl_gcc_warnings = no], if test $emacs_cv_clang = yes; then nw="$nw -Wcast-align" nw="$nw -Wdouble-promotion" + nw="$nw -Wmissing-braces" fi # This causes too much noise in the MinGW build commit acd58c9198c08c3eb631a3f036b4f95073f7fe10 Author: Noam Postavsky Date: Sun Apr 23 22:30:20 2017 -0400 Limit integers printed as characters (Bug#16828) * lisp/simple.el (eval-expression-print-maximum-character): New variable. (eval-expression-print-format): Only display value as character if it's less than or equal to `eval-expression-print-maximum-character'. (eval-expression-get-print-arguments): Check eval-expression-print-maximum-character, allow negative arg to override it. (eval-expression): * lisp/progmodes/elisp-mode.el (elisp--eval-last-sexp): (elisp--eval-last-sexp-print-value): Handle new variable. * doc/emacs/building.texi (Lisp Eval): Document new variable and behavior. * etc/NEWS: Announce it. * test/lisp/progmodes/elisp-mode-tests.el (eval-last-sexp-print-format-small-int) (eval-last-sexp-print-format-small-int-echo) (eval-last-sexp-print-format-large-int) (eval-last-sexp-print-format-large-int-echo): * test/lisp/simple-tests.el (eval-expression-print-format-small-int) (eval-expression-print-format-small-int-echo) (eval-expression-print-format-large-int) (eval-expression-print-format-large-int-echo): New tests. diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index ba8eae0759..f7eb8fe9ea 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -1485,7 +1485,9 @@ expression.) Emacs Lisp expression preceding point in the buffer, and displays the value in the echo area. When the result of an evaluation is an integer, it is displayed together with the value in other formats -(octal, hexadecimal, and character). +(octal, hexadecimal, and character if +@code{eval-expression-print-maximum-character}, described below, +allows it). If @kbd{M-:} or @kbd{C-x C-e} is given a prefix argument, it inserts the value into the current buffer at point, rather than displaying it @@ -1493,8 +1495,10 @@ in the echo area. If the prefix argument is zero, any integer output is inserted together with its value in other formats (octal, hexadecimal, and character). Such a prefix argument also prevents abbreviation of the output according to the variables -@code{eval-expression-print-level} and @code{eval-expression-print-length} -(see below). +@code{eval-expression-print-level} and +@code{eval-expression-print-length} (see below). Similarly, a prefix +argument of @code{-1} overrides the effect of +@code{eval-expression-print-length}. @kindex C-M-x @r{(Emacs Lisp mode)} @findex eval-defun @@ -1524,6 +1528,7 @@ eval-buffer} is similar but evaluates the entire buffer. @vindex eval-expression-print-level @vindex eval-expression-print-length +@vindex eval-expression-print-maximum-character @vindex eval-expression-debug-on-error The options @code{eval-expression-print-level} and @code{eval-expression-print-length} control the maximum depth and @@ -1533,6 +1538,8 @@ before abbreviating them. Supplying a zero prefix argument to printed in full. @code{eval-expression-debug-on-error} controls whether evaluation errors invoke the debugger when these commands are used; its default is @code{t}. +@code{eval-expression-print-maximum-character} prevents integers which +are larger than it from being displayed as characters. @node Lisp Interaction @section Lisp Interaction Buffers diff --git a/etc/NEWS b/etc/NEWS index 340718ecbc..aa579b11c7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -352,6 +352,10 @@ environment variable on a remote machine to emacsclient, and use the local Emacs to edit remote files via Tramp. See the node "emacsclient Options" in the user manual for the details. ++++ +** The new variable 'eval-expression-print-maximum-character' prevents +large integers from being displayed as characters. + * Editing Changes in Emacs 26.1 diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index c2fdba47a0..6c6fb92504 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1120,24 +1120,25 @@ output with no limit on the length and level of lists, and include additional formats for integers \(octal, hexadecimal, and character)." (pcase-let* - ((`(,insert-value ,no-truncate ,char-print) + ((`(,insert-value ,no-truncate ,char-print-limit) (eval-expression-get-print-arguments eval-last-sexp-arg-internal))) ;; Setup the lexical environment if lexical-binding is enabled. (elisp--eval-last-sexp-print-value (eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding) - (if insert-value (current-buffer) t) no-truncate char-print))) + (if insert-value (current-buffer) t) no-truncate char-print-limit))) (defun elisp--eval-last-sexp-print-value - (value output &optional no-truncate char-print) + (value output &optional no-truncate char-print-limit) (let* ((unabbreviated (let ((print-length nil) (print-level nil)) (prin1-to-string value))) + (eval-expression-print-maximum-character char-print-limit) (print-length (unless no-truncate eval-expression-print-length)) (print-level (unless no-truncate eval-expression-print-level)) (beg (point)) end) (prog1 (prin1 value output) - (let ((str (and char-print (eval-expression-print-format value)))) + (let ((str (and char-print-limit (eval-expression-print-format value)))) (if str (princ str output))) (setq end (point)) (when (and (bufferp output) @@ -1175,14 +1176,17 @@ POS specifies the starting position where EXP was found and defaults to point." (defun eval-last-sexp (eval-last-sexp-arg-internal) "Evaluate sexp before point; print value in the echo area. -Interactively, with prefix argument, print output into current buffer. +Interactively, with a non `-' prefix argument, print output into +current buffer. -Normally, this function truncates long output according to the value -of the variables `eval-expression-print-length' and +Normally, this function truncates long output according to the +value of the variables `eval-expression-print-length' and `eval-expression-print-level'. With a prefix argument of zero, however, there is no such truncation. Such a prefix argument also causes integers to be printed in several additional formats -\(octal, hexadecimal, and character). +\(octal, hexadecimal, and character when the prefix argument is +-1 or the integer is `eval-expression-print-maximum-character' or +less). If `eval-expression-debug-on-error' is non-nil, which is the default, this command arranges for all errors to enter the debugger." diff --git a/lisp/simple.el b/lisp/simple.el index 3af62657db..ea3a495fbc 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1450,15 +1450,24 @@ If nil, don't change the value of `debug-on-error'." :type 'boolean :version "21.1") +(defcustom eval-expression-print-maximum-character 127 + "The largest integer that will be displayed as a character. +This affects printing by `eval-expression' (via +`eval-expression-print-format')." + :group 'lisp + :type 'integer + :version "26.1") + (defun eval-expression-print-format (value) "If VALUE in an integer, return a specially formatted string. This string will typically look like \" (#o1, #x1, ?\\C-a)\". If VALUE is not an integer, nil is returned. -This function is used by functions like `prin1' that display the -result of expression evaluation." +This function is used by commands like `eval-expression' that +display the result of expression evaluation." (when (integerp value) (let ((char-string (and (characterp value) + (<= value eval-expression-print-maximum-character) (char-displayable-p value) (prin1-char value)))) (if char-string @@ -1484,32 +1493,40 @@ result of expression evaluation." (defun eval-expression-get-print-arguments (prefix-argument) "Get arguments for commands that print an expression result. -Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT) +Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT-LIMIT) based on PREFIX-ARG. This function determines the interpretation of the prefix argument for `eval-expression' and `eval-last-sexp'." (let ((num (prefix-numeric-value prefix-argument))) - (list (not (memq prefix-argument '(nil))) + (list (not (memq prefix-argument '(- nil))) (= num 0) - (cond ((not (memq prefix-argument '(0 nil))) nil) - (t t))))) + (cond ((not (memq prefix-argument '(0 -1 - nil))) nil) + ((= num -1) most-positive-fixnum) + (t eval-expression-print-maximum-character))))) ;; We define this, rather than making `eval' interactive, ;; for the sake of completion of names like eval-region, eval-buffer. -(defun eval-expression (exp &optional insert-value no-truncate char-print) +(defun eval-expression (exp &optional insert-value no-truncate char-print-limit) "Evaluate EXP and print value in the echo area. -When called interactively, read an Emacs Lisp expression and evaluate it. -Value is also consed on to front of the variable `values'. -If the resulting value is an integer, it will be printed in -several additional formats (octal, hexadecimal, and character). -Optional argument INSERT-VALUE non-nil (interactively, with -prefix argument) means insert the result into the current buffer -instead of printing it in the echo area. - -Normally, this function truncates long output according to the value -of the variables `eval-expression-print-length' and -`eval-expression-print-level'. With a prefix argument of zero, -however, there is no such truncation. +When called interactively, read an Emacs Lisp expression and +evaluate it. Value is also consed on to front of the variable +`values'. Optional argument INSERT-VALUE non-nil (interactively, +with a non `-' prefix argument) means insert the result into the +current buffer instead of printing it in the echo area. + +Normally, this function truncates long output according to the +value of the variables `eval-expression-print-length' and +`eval-expression-print-level'. When NO-TRUNCATE is +non-nil (interactively, with a prefix argument of zero), however, +there is no such truncation. + +If the resulting value is an integer, and CHAR-PRINT-LIMIT is +non-nil (interactively, unless given a positive prefix argument) +it will be printed in several additional formats (octal, +hexadecimal, and character). The character format is only used +if the value is below CHAR-PRINT-LIMIT (interactively, if the +prefix argument is -1 or the value is below +`eval-expression-print-maximum-character'). Runs the hook `eval-expression-minibuffer-setup-hook' on entering the minibuffer. @@ -1535,11 +1552,12 @@ this command arranges for all errors to enter the debugger." (let ((print-length (unless no-truncate eval-expression-print-length)) (print-level (unless no-truncate eval-expression-print-level)) + (eval-expression-print-maximum-character char-print-limit) (deactivate-mark)) (let ((out (if insert-value (current-buffer) t))) (prog1 (prin1 (car values) out) - (let ((str (and char-print + (let ((str (and char-print-limit (eval-expression-print-format (car values))))) (when str (princ str out))))))) diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el index 5edb590b1e..03ae8481ee 100644 --- a/test/lisp/progmodes/elisp-mode-tests.el +++ b/test/lisp/progmodes/elisp-mode-tests.el @@ -132,6 +132,54 @@ (call-interactively #'eval-last-sexp) (should (equal (current-message) "t"))))) +(ert-deftest eval-last-sexp-print-format-small-int () + (with-temp-buffer + (let ((current-prefix-arg '(4))) + (erase-buffer) (insert "?A") + (call-interactively #'eval-last-sexp) + (should (equal (buffer-string) "?A65"))) + (let ((current-prefix-arg 0)) + (erase-buffer) (insert "?A") + (call-interactively #'eval-last-sexp) + (should (equal (buffer-string) "?A65 (#o101, #x41, ?A)"))))) + +(ert-deftest eval-last-sexp-print-format-small-int-echo () + (skip-unless (not noninteractive)) + (with-temp-buffer + (let ((current-prefix-arg nil)) + (erase-buffer) (insert "?A") (message nil) + (call-interactively #'eval-last-sexp) + (should (equal (current-message) "65 (#o101, #x41, ?A)"))))) + +(ert-deftest eval-last-sexp-print-format-large-int () + (with-temp-buffer + (let ((eval-expression-print-maximum-character ?A)) + (let ((current-prefix-arg '(4))) + (erase-buffer) (insert "?B") + (call-interactively #'eval-last-sexp) + (should (equal (buffer-string) "?B66"))) + (let ((current-prefix-arg 0)) + (erase-buffer) (insert "?B") + (call-interactively #'eval-last-sexp) + (should (equal (buffer-string) "?B66 (#o102, #x42)"))) + (let ((current-prefix-arg -1)) + (erase-buffer) (insert "?B") + (call-interactively #'eval-last-sexp) + (should (equal (buffer-string) "?B66 (#o102, #x42, ?B)")))))) + +(ert-deftest eval-last-sexp-print-format-large-int-echo () + (skip-unless (not noninteractive)) + (with-temp-buffer + (let ((eval-expression-print-maximum-character ?A)) + (let ((current-prefix-arg nil)) + (erase-buffer) (insert "?B") (message nil) + (call-interactively #'eval-last-sexp) + (should (equal (current-message) "66 (#o102, #x42)"))) + (let ((current-prefix-arg '-)) + (erase-buffer) (insert "?B") (message nil) + (call-interactively #'eval-last-sexp) + (should (equal (current-message) "66 (#o102, #x42, ?B)")))))) + ;;; xref (defun xref-elisp-test-descr-to-target (xref) diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index b74e28ccaf..180dcc0a20 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -396,5 +396,57 @@ See Bug#21722." (call-interactively #'eval-expression) (should (equal (current-message) "t")))))) +(ert-deftest eval-expression-print-format-small-int () + (with-temp-buffer + (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?A))) + (let ((current-prefix-arg '(4))) + (erase-buffer) + (call-interactively #'eval-expression) + (should (equal (buffer-string) "65"))) + (let ((current-prefix-arg 0)) + (erase-buffer) + (call-interactively #'eval-expression) + (should (equal (buffer-string) "65 (#o101, #x41, ?A)")))))) + +(ert-deftest eval-expression-print-format-small-int-echo () + (skip-unless (not noninteractive)) + (with-temp-buffer + (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?A))) + (let ((current-prefix-arg nil)) + (message nil) + (call-interactively #'eval-expression) + (should (equal (current-message) "65 (#o101, #x41, ?A)")))))) + +(ert-deftest eval-expression-print-format-large-int () + (with-temp-buffer + (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?B)) + (eval-expression-print-maximum-character ?A)) + (let ((current-prefix-arg '(4))) + (erase-buffer) + (call-interactively #'eval-expression) + (should (equal (buffer-string) "66"))) + (let ((current-prefix-arg 0)) + (erase-buffer) + (call-interactively #'eval-expression) + (should (equal (buffer-string) "66 (#o102, #x42)"))) + (let ((current-prefix-arg -1)) + (erase-buffer) + (call-interactively #'eval-expression) + (should (equal (buffer-string) "66 (#o102, #x42, ?B)")))))) + +(ert-deftest eval-expression-print-format-large-int-echo () + (skip-unless (not noninteractive)) + (with-temp-buffer + (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?B)) + (eval-expression-print-maximum-character ?A)) + (let ((current-prefix-arg nil)) + (message nil) + (call-interactively #'eval-expression) + (should (equal (current-message) "66 (#o102, #x42)"))) + (let ((current-prefix-arg '-)) + (message nil) + (call-interactively #'eval-expression) + (should (equal (current-message) "66 (#o102, #x42, ?B)")))))) + (provide 'simple-test) ;;; simple-test.el ends here commit 267be4bdc28564a99f45da29e84eb98838117b50 Author: Noam Postavsky Date: Sun Apr 23 22:21:42 2017 -0400 Refactor lisp eval result printing * lisp/simple.el (eval-expression-print-format): Don't check `standard-output' or `current-prefix-arg'. (eval-expression-get-print-arguments): New function, centralizes decision about how to print results of `eval-expression' and `eval-last-sexp'. (eval-expression): * lisp/progmodes/elisp-mode.el (elisp--eval-last-sexp-print-value): Use it. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 53a0f66439..c2fdba47a0 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1119,29 +1119,28 @@ current buffer. If EVAL-LAST-SEXP-ARG-INTERNAL is `0', print output with no limit on the length and level of lists, and include additional formats for integers \(octal, hexadecimal, and character)." - (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))) + (pcase-let* + ((`(,insert-value ,no-truncate ,char-print) + (eval-expression-get-print-arguments eval-last-sexp-arg-internal))) ;; Setup the lexical environment if lexical-binding is enabled. (elisp--eval-last-sexp-print-value (eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding) - eval-last-sexp-arg-internal))) - -(defun elisp--eval-last-sexp-print-value (value &optional eval-last-sexp-arg-internal) - (let ((unabbreviated (let ((print-length nil) (print-level nil)) - (prin1-to-string value))) - (print-length (and (not (zerop (prefix-numeric-value - eval-last-sexp-arg-internal))) - eval-expression-print-length)) - (print-level (and (not (zerop (prefix-numeric-value - eval-last-sexp-arg-internal))) - eval-expression-print-level)) - (beg (point)) - end) + (if insert-value (current-buffer) t) no-truncate char-print))) + +(defun elisp--eval-last-sexp-print-value + (value output &optional no-truncate char-print) + (let* ((unabbreviated (let ((print-length nil) (print-level nil)) + (prin1-to-string value))) + (print-length (unless no-truncate eval-expression-print-length)) + (print-level (unless no-truncate eval-expression-print-level)) + (beg (point)) + end) (prog1 - (prin1 value) - (let ((str (eval-expression-print-format value))) - (if str (princ str))) + (prin1 value output) + (let ((str (and char-print (eval-expression-print-format value)))) + (if str (princ str output))) (setq end (point)) - (when (and (bufferp standard-output) + (when (and (bufferp output) (or (not (null print-length)) (not (null print-level))) (not (string= unabbreviated diff --git a/lisp/simple.el b/lisp/simple.el index 7f13df5006..3af62657db 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1456,16 +1456,14 @@ This string will typically look like \" (#o1, #x1, ?\\C-a)\". If VALUE is not an integer, nil is returned. This function is used by functions like `prin1' that display the result of expression evaluation." - (if (and (integerp value) - (or (eq standard-output t) - (zerop (prefix-numeric-value current-prefix-arg)))) - (let ((char-string - (if (and (characterp value) - (char-displayable-p value)) - (prin1-char value)))) - (if char-string - (format " (#o%o, #x%x, %s)" value value char-string) - (format " (#o%o, #x%x)" value value))))) + (when (integerp value) + (let ((char-string + (and (characterp value) + (char-displayable-p value) + (prin1-char value)))) + (if char-string + (format " (#o%o, #x%x, %s)" value value char-string) + (format " (#o%o, #x%x)" value value))))) (defvar eval-expression-minibuffer-setup-hook nil "Hook run by `eval-expression' when entering the minibuffer.") @@ -1484,9 +1482,21 @@ result of expression evaluation." read-expression-map t 'read-expression-history)))) +(defun eval-expression-get-print-arguments (prefix-argument) + "Get arguments for commands that print an expression result. +Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT) +based on PREFIX-ARG. This function determines the interpretation +of the prefix argument for `eval-expression' and +`eval-last-sexp'." + (let ((num (prefix-numeric-value prefix-argument))) + (list (not (memq prefix-argument '(nil))) + (= num 0) + (cond ((not (memq prefix-argument '(0 nil))) nil) + (t t))))) + ;; We define this, rather than making `eval' interactive, ;; for the sake of completion of names like eval-region, eval-buffer. -(defun eval-expression (exp &optional insert-value) +(defun eval-expression (exp &optional insert-value no-truncate char-print) "Evaluate EXP and print value in the echo area. When called interactively, read an Emacs Lisp expression and evaluate it. Value is also consed on to front of the variable `values'. @@ -1507,8 +1517,8 @@ minibuffer. If `eval-expression-debug-on-error' is non-nil, which is the default, this command arranges for all errors to enter the debugger." (interactive - (list (read--expression "Eval: ") - current-prefix-arg)) + (cons (read--expression "Eval: ") + (eval-expression-get-print-arguments current-prefix-arg))) (if (null eval-expression-debug-on-error) (push (eval exp lexical-binding) values) @@ -1523,23 +1533,15 @@ this command arranges for all errors to enter the debugger." (unless (eq old-value new-value) (setq debug-on-error new-value)))) - (let ((print-length (and (not (zerop (prefix-numeric-value insert-value))) - eval-expression-print-length)) - (print-level (and (not (zerop (prefix-numeric-value insert-value))) - eval-expression-print-level)) + (let ((print-length (unless no-truncate eval-expression-print-length)) + (print-level (unless no-truncate eval-expression-print-level)) (deactivate-mark)) - (if insert-value - (with-no-warnings - (let ((standard-output (current-buffer))) - (prog1 - (prin1 (car values)) - (when (zerop (prefix-numeric-value insert-value)) - (let ((str (eval-expression-print-format (car values)))) - (if str (princ str))))))) + (let ((out (if insert-value (current-buffer) t))) (prog1 - (prin1 (car values) t) - (let ((str (eval-expression-print-format (car values)))) - (if str (princ str t))))))) + (prin1 (car values) out) + (let ((str (and char-print + (eval-expression-print-format (car values))))) + (when str (princ str out))))))) (defun edit-and-eval-command (prompt command) "Prompting with PROMPT, let user edit COMMAND and eval result. diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el index 93c428b2d2..5edb590b1e 100644 --- a/test/lisp/progmodes/elisp-mode-tests.el +++ b/test/lisp/progmodes/elisp-mode-tests.el @@ -114,6 +114,24 @@ (should (member "backup-buffer" comps)) (should-not (member "backup-inhibited" comps))))) +;;; eval-last-sexp + +(ert-deftest eval-last-sexp-print-format-sym () + (with-temp-buffer + (let ((current-prefix-arg '(4))) + (erase-buffer) (insert "t") + (call-interactively #'eval-last-sexp) + (should (equal (buffer-string) "tt"))))) + +(ert-deftest eval-last-sexp-print-format-sym-echo () + ;; We can only check the echo area when running interactive. + (skip-unless (not noninteractive)) + (with-temp-buffer + (let ((current-prefix-arg nil)) + (erase-buffer) (insert "t") (message nil) + (call-interactively #'eval-last-sexp) + (should (equal (current-message) "t"))))) + ;;; xref (defun xref-elisp-test-descr-to-target (xref) diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index f4849c4b21..b74e28ccaf 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -20,6 +20,7 @@ ;;; Code: (require 'ert) +(eval-when-compile (require 'cl-lib)) (defmacro simple-test--dummy-buffer (&rest body) (declare (indent 0) @@ -35,6 +36,8 @@ (buffer-substring (point) (point-max)))))) + +;;; `transpose-sexps' (defmacro simple-test--transpositions (&rest body) (declare (indent 0) (debug t)) @@ -46,6 +49,13 @@ (cons (buffer-substring (point-min) (point)) (buffer-substring (point) (point-max))))) +;;; Transposition with negative args (bug#20698, bug#21885) +(ert-deftest simple-transpose-subr () + (should (equal (simple-test--transpositions (transpose-sexps -1)) + '("(s1) (s2) (s4)" . " (s3) (s5)"))) + (should (equal (simple-test--transpositions (transpose-sexps -2)) + '("(s1) (s4)" . " (s2) (s3) (s5)")))) + ;;; `newline' (ert-deftest newline () @@ -239,8 +249,8 @@ (should (equal ?\s (char-syntax ?\f))) (should (equal ?\s (char-syntax ?\n)))))) - -;;; auto-boundary tests + +;;; undo auto-boundary tests (ert-deftest undo-auto-boundary-timer () (should undo-auto-current-boundary-timer)) @@ -269,14 +279,6 @@ (insert "hello") (undo-auto--boundaries 'test)))) -;;; Transposition with negative args (bug#20698, bug#21885) -(ert-deftest simple-transpose-subr () - (should (equal (simple-test--transpositions (transpose-sexps -1)) - '("(s1) (s2) (s4)" . " (s3) (s5)"))) - (should (equal (simple-test--transpositions (transpose-sexps -2)) - '("(s1) (s4)" . " (s2) (s3) (s5)")))) - - ;; Test for a regression introduced by undo-auto--boundaries changes. ;; https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg01652.html (defun undo-test-kill-c-a-then-undo () @@ -374,5 +376,25 @@ See Bug#21722." (undo) (point))))) + +;;; `eval-expression' + +(ert-deftest eval-expression-print-format-sym () + (with-temp-buffer + (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) t))) + (let ((current-prefix-arg '(4))) + (call-interactively #'eval-expression) + (should (equal (buffer-string) "t")))))) + +(ert-deftest eval-expression-print-format-sym-echo () + ;; We can only check the echo area when running interactive. + (skip-unless (not noninteractive)) + (with-temp-buffer + (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) t))) + (let ((current-prefix-arg nil)) + (message nil) + (call-interactively #'eval-expression) + (should (equal (current-message) "t")))))) + (provide 'simple-test) ;;; simple-test.el ends here commit c1c8b67246c4314b302cca2ac43f13a0baba4c16 Author: Paul Eggert Date: Fri May 19 13:43:03 2017 -0700 Check that signed right shift is arithmetic * src/data.c (ash_lsh_impl): Verify that signed right shift is arithmetic; if we run across a compiler that uses a logical shift we’ll need to complicate the code before removing this compile-time check. Help the compiler do common subexpression elimination better. diff --git a/src/data.c b/src/data.c index 3ff2a80974..4242b90e62 100644 --- a/src/data.c +++ b/src/data.c @@ -3066,9 +3066,12 @@ usage: (logxor &rest INTS-OR-MARKERS) */) } static Lisp_Object -ash_lsh_impl (register Lisp_Object value, Lisp_Object count, bool lsh) +ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh) { - register Lisp_Object val; + /* This code assumes that signed right shifts are arithmetic. */ + verify ((EMACS_INT) -1 >> 1 == -1); + + Lisp_Object val; CHECK_NUMBER (value); CHECK_NUMBER (count); @@ -3076,12 +3079,12 @@ ash_lsh_impl (register Lisp_Object value, Lisp_Object count, bool lsh) if (XINT (count) >= EMACS_INT_WIDTH) XSETINT (val, 0); else if (XINT (count) > 0) - XSETINT (val, XUINT (value) << XFASTINT (count)); + XSETINT (val, XUINT (value) << XINT (count)); else if (XINT (count) <= -EMACS_INT_WIDTH) XSETINT (val, lsh ? 0 : XINT (value) < 0 ? -1 : 0); else - XSETINT (val, lsh ? XUINT (value) >> -XINT (count) : \ - XINT (value) >> -XINT (count)); + XSETINT (val, (lsh ? XUINT (value) >> -XINT (count) + : XINT (value) >> -XINT (count))); return val; } commit 7ff8c5cae02afa511d11b4b32d1a56f7070bfb97 Author: Paul Eggert Date: Fri May 19 10:38:22 2017 -0700 Minor .gitignore fixes * .gitignore: modules/mod-test/Makefile was renamed to test/data/emacs-module/Makefile. Omit [0-9]*.core, subsumed by *.core. test/indent/*.new was renamed to test/manual/indent/*.new. Add *.swp, for Vim. diff --git a/.gitignore b/.gitignore index fa9353453c..6dd21124e8 100644 --- a/.gitignore +++ b/.gitignore @@ -34,11 +34,11 @@ InfoPlist.strings Makefile makefile !etc/refcards/Makefile -!modules/mod-test/Makefile +!test/data/emacs-module/Makefile !test/lisp/progmodes/flymake-resources/Makefile -!test/manual/indent/Makefile !test/manual/etags/Makefile !test/manual/etags/make-src/Makefile +!test/manual/indent/Makefile /*.cache /confdefs.h /config.status @@ -132,7 +132,6 @@ src/gl-stamp *.o *.res *.so -[0-9]*.core core core.*[0-9] gmon.out @@ -141,12 +140,12 @@ oo-spd/ src/*.map # Tests. -test/indent/*.new test/manual/biditest.txt test/manual/etags/srclist test/manual/etags/regexfile test/manual/etags/ETAGS test/manual/etags/CTAGS +test/manual/indent/*.new # ctags, etags. TAGS @@ -244,6 +243,7 @@ gnustmp* # Version control and locks. *.orig *.rej +*.swp *~ .#* \#*\# commit c7391db7dbafc674ff393f8f9fbdb018e0126380 Author: Eli Zaretskii Date: Fri May 19 18:18:04 2017 +0300 ; * doc/emacs/files.texi (Auto Save Files): Fix a cross-reference. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 5e6afa5506..36f4fbdf3a 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1055,7 +1055,7 @@ non-@code{nil} value, that buffer won't be affected by customize the interval between auto-save operations in @code{auto-save-visited-mode}; by default it's five seconds. @code{auto-save-interval} and @code{auto-save-timeout} have no effect -on @code{auto-save-visited-mode}. @xref{Auto Save Control} for +on @code{auto-save-visited-mode}. @xref{Auto Save Control}, for details on these variables. @vindex delete-auto-save-files commit b372e565e4b2b9aaedfdc7d4a43ebc7ad3f66120 Author: Stefan Monnier Date: Fri May 19 09:42:57 2017 -0400 * lisp/emacs-lisp/package.el: Quote `package-desc' in docstrings diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index c0ecb0447f..551f440a8f 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -638,7 +638,7 @@ Return the max version (as a string) if the package is held at a lower version." (t (error "Invalid element in `package-load-list'"))))) (defun package-built-in-p (package &optional min-version) - "Return true if PACKAGE is built-in to Emacs. + "Return non-nil if PACKAGE is built-in to Emacs. Optional arg MIN-VERSION, if non-nil, should be a version list specifying the minimum acceptable version." (if (package-desc-p package) ;; was built-in and then was converted @@ -1776,7 +1776,7 @@ destructively set to nil in ONLY." That is, any element of the returned list is guaranteed to not directly depend on any elements that come before it. -PACKAGE-LIST is a list of package-desc objects. +PACKAGE-LIST is a list of `package-desc' objects. Indirect dependencies are guaranteed to be returned in order only if all the in-between dependencies are also in PACKAGE-LIST." (let ((alist (mapcar (lambda (p) (cons (package-desc-name p) p)) package-list)) @@ -1845,11 +1845,11 @@ if all the in-between dependencies are also in PACKAGE-LIST." (setf (package-desc-signed (car pkg-descs)) t)))))))))) (defun package-installed-p (package &optional min-version) - "Return true if PACKAGE, of MIN-VERSION or newer, is installed. + "Return non-nil if PACKAGE, of MIN-VERSION or newer, is installed. If PACKAGE is a symbol, it is the package name and MIN-VERSION should be a version list. -If PACKAGE is a package-desc object, MIN-VERSION is ignored." +If PACKAGE is a `package-desc' object, MIN-VERSION is ignored." (unless package--initialized (error "package.el is not yet initialized!")) (if (package-desc-p package) (let ((dir (package-desc-dir package))) @@ -1865,7 +1865,7 @@ If PACKAGE is a package-desc object, MIN-VERSION is ignored." (defun package-download-transaction (packages) "Download and install all the packages in PACKAGES. -PACKAGES should be a list of package-desc. +PACKAGES should be a list of `package-desc'. This function assumes that all package requirements in PACKAGES are satisfied, i.e. that PACKAGES is computed using `package-compute-transaction'." @@ -1932,13 +1932,13 @@ add a call to it along with some explanatory comments." ;;;###autoload (defun package-install (pkg &optional dont-select) "Install the package PKG. -PKG can be a package-desc or a symbol naming one of the available packages +PKG can be a `package-desc' or a symbol naming one of the available packages in an archive in `package-archives'. Interactively, prompt for its name. If called interactively or if DONT-SELECT nil, add PKG to `package-selected-packages'. -If PKG is a package-desc and it is already installed, don't try +If PKG is a `package-desc' and it is already installed, don't try to install it but still mark it as selected." (interactive (progn @@ -2067,7 +2067,7 @@ If some packages are not installed propose to install them." ;;; Package Deletion (defun package--newest-p (pkg) - "Return t if PKG is the newest package with its name." + "Return non-nil if PKG is the newest package with its name." (equal (cadr (assq (package-desc-name pkg) package-alist)) pkg)) @@ -2142,7 +2142,7 @@ If NOSAVE is non-nil, the package is not removed from ;;;###autoload (defun package-reinstall (pkg) "Reinstall package PKG. -PKG should be either a symbol, the package name, or a package-desc +PKG should be either a symbol, the package name, or a `package-desc' object." (interactive (list (intern (completing-read "Reinstall package: " @@ -2567,7 +2567,7 @@ package PKG-DESC, add one. The alist is keyed with PKG-DESC." (defun package--incompatible-p (pkg &optional shallow) "Return non-nil if PKG has no chance of being installable. -PKG is a package-desc object. +PKG is a `package-desc' object. If SHALLOW is non-nil, this only checks if PKG depends on a higher `emacs-version' than the one being used. Otherwise, also @@ -2651,7 +2651,7 @@ Installed obsolete packages are always displayed.") (defun package--remove-hidden (pkg-list) "Filter PKG-LIST according to `package-archive-priorities'. -PKG-LIST must be a list of package-desc objects, all with the +PKG-LIST must be a list of `package-desc' objects, all with the same name, sorted by decreasing `package-desc-priority-version'. Return a list of packages tied for the highest priority according to their archives." @@ -2905,7 +2905,7 @@ Return (PKG-DESC [NAME VERSION STATUS DOC])." ;;; Package menu printing (defun package-menu--print-info-simple (pkg) "Return a package entry suitable for `tabulated-list-entries'. -PKG is a package-desc object. +PKG is a `package-desc' object. Return (PKG-DESC [NAME VERSION STATUS DOC])." (let* ((status (package-desc-status pkg)) (face (pcase status commit c1c6f167b2e683db3e2cee7cb29ab2eb745e1713 Author: Nick Helm Date: Fri May 19 15:20:59 2017 +0300 Fix turning off whitespace-mode * lisp/whitespace.el (whitespace-display-char-on): Correct the way the original buffer-display-table is saved and restored when global-whitespace-mode is active. (Bug#26892) * test/lisp/whitespace-tests.el (whitespace-tests-whitespace-mode-on): New function. (whitespace-tests-display-tables): New test. Copyright-paperwork-exempt: yes diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 6aca47cd43..c6d5b16cae 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -2373,9 +2373,10 @@ Also refontify when necessary." (let (vecs vec) ;; Remember whether a buffer has a local display table. (unless whitespace-display-table-was-local - (setq whitespace-display-table-was-local t - whitespace-display-table - (copy-sequence buffer-display-table)) + (setq whitespace-display-table-was-local t) + (unless (or whitespace-mode global-whitespace-mode) + (setq whitespace-display-table + (copy-sequence buffer-display-table))) ;; Assure `buffer-display-table' is unique ;; when two or more windows are visible. (setq buffer-display-table diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el index 99cc3c4ec0..1e455352f2 100644 --- a/test/lisp/whitespace-tests.el +++ b/test/lisp/whitespace-tests.el @@ -47,6 +47,40 @@ (should (equal (whitespace-tests--cleanup-string "a \n\t \n\n") "a \n")))) + +;; We cannot call whitespace-mode because it will do nothing in batch +;; mode. So we call its innards instead. +(defun whitespace-tests-whitespace-mode-on () + "Turn whitespace-mode on even in batch mode." + (whitespace-turn-on) + (whitespace-action-when-on) + (setq whitespace-mode t)) + +(ert-deftest whitespace-tests-display-tables () + "Test whitespace stores and restores the buffer display table - bug26892." + (with-temp-buffer + (whitespace-mode -1) ; turn off in case global ws mode is active + (let ((whitespace-style '(space-mark tab-mark newline-mark)) + (whitespace-display-mappings '((space-mark 32 [183] [46]) + (space-mark 160 [164] [95]) + (newline-mark 10 [36 10]) + (tab-mark 9 [187 9] [92 9]))) + (buffer-display-table nil)) + ;test the display table actually changes + (should-not (equal nil + (progn (whitespace-tests-whitespace-mode-on) + buffer-display-table))) + ;test the display table restores correctly + (should (equal nil + (progn (whitespace-turn-off) + buffer-display-table))) + ;test the stored display table is preserved + (should (equal nil + (progn (whitespace-tests-whitespace-mode-on) + (whitespace-tests-whitespace-mode-on) + (whitespace-turn-off) + buffer-display-table)))))) + (provide 'whitespace-tests) ;;; whitespace-tests.el ends here commit 1b0ec9f1b5c2587d6cd402f59f8ec14d81d3e551 Author: Michael Albinus Date: Fri May 19 13:57:36 2017 +0200 Minor tweaks in tramp-tests.el * test/lisp/net/tramp-tests.el (tramp--test-afp-or-smb-p): New defun. (tramp-test05-expand-file-name-relative): Use it. (tramp-test38-unload): Run only in batch mode. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index bcf2e840fd..49c32dbaaf 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -1622,6 +1622,13 @@ handled properly. BODY shall not contain a timeout." "Check `expand-file-name'." ;; Mark as failed until bug has been fixed. :expected-result :failed + (skip-unless (tramp--test-enabled)) + ;; File names with a share behave differently. + (when (tramp--test-afp-or-smb-p) + (setf (ert-test-expected-result-type + (ert-get-test 'tramp-test05-expand-file-name-relative)) + :passed)) + (should (string-equal (let ((default-directory @@ -3220,6 +3227,13 @@ This requires restrictions of file name syntax." (or (eq system-type 'windows-nt) (tramp-smb-file-name-p tramp-test-temporary-file-directory))) +(defun tramp--test-afp-or-smb-p () + "Check, whether the afp or smb method is used. +This requires an additional share name." + (or (string-equal + "afp" (file-remote-p tramp-test-temporary-file-directory 'method)) + (tramp-smb-file-name-p tramp-test-temporary-file-directory))) + (defun tramp--test-check-files (&rest files) "Run a simple but comprehensive test over every file in FILES." ;; TODO: The quoted case does not work. @@ -3708,6 +3722,8 @@ Since it unloads Tramp, it shall be the last test to run." ;; Mark as failed until all symbols are unbound. :expected-result (if (featurep 'tramp) :failed :passed) :tags '(:expensive-test) + (skip-unless noninteractive) + (when (featurep 'tramp) (unload-feature 'tramp 'force) ;; No Tramp feature must be left. commit 6de77cfa9da18c5e3765c6202b61cef86409e130 Author: Michael Albinus Date: Fri May 19 13:57:04 2017 +0200 Fix a problem with OpenSSH 7 in Tramp * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options): Set also "ConnectTimeout" during test. Otherwise, OpenSSH 7 will hang. diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index e61b0ce526..9b001a90e7 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -4592,8 +4592,10 @@ Goes through the list `tramp-inline-compress-commands'." (with-temp-buffer ;; We use a non-existing IP address, in order to ;; avoid useless connections, and DNS timeouts. + ;; Setting ConnectTimeout is needed since OpenSSH 7. (tramp-call-process - vec "ssh" nil t nil "-o" "ControlPath=%C" "0.0.0.1") + vec "ssh" nil t nil + "-o" "ConnectTimeout=1" "-o" "ControlPath=%C" "0.0.0.1") (goto-char (point-min)) (setq tramp-ssh-controlmaster-options (concat tramp-ssh-controlmaster-options commit d35da215cdc6e3734a967417f2df41b312fac854 Author: Jean-Christophe Helary Date: Fri May 19 14:44:33 2017 +0300 Improve documentation of 'split-string' * doc/lispref/strings.texi (Creating Strings): Rearrange text to make it more readable. (Bug#26925) diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 1d766869b1..9436a96ead 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -279,17 +279,26 @@ expression @var{separators} (@pxref{Regular Expressions}). Each match for @var{separators} defines a splitting point; the substrings between splitting points are made into a list, which is returned. +If @var{separators} is @code{nil} (or omitted), the default is the +value of @code{split-string-default-separators} and the function +behaves as if @var{omit-nulls} were @code{t}. + If @var{omit-nulls} is @code{nil} (or omitted), the result contains null strings whenever there are two consecutive matches for @var{separators}, or a match is adjacent to the beginning or end of @var{string}. If @var{omit-nulls} is @code{t}, these null strings are omitted from the result. -If @var{separators} is @code{nil} (or omitted), the default is the -value of @code{split-string-default-separators}. +If the optional argument @var{trim} is non-@code{nil}, it should be a +regular expression to match text to trim from the beginning and end of +each substring. If trimming makes the substring empty, it is treated +as null. + +If you need to split a string into a list of individual command-line +arguments suitable for @code{call-process} or @code{start-process}, +see @ref{Shell Arguments, split-string-and-unquote}. -As a special case, when @var{separators} is @code{nil} (or omitted), -null strings are always omitted from the result. Thus: +Examples: @example (split-string " two words ") @@ -306,8 +315,6 @@ useful. If you need such a result, use an explicit value for @result{} ("" "two" "words" "") @end example -More examples: - @example (split-string "Soup is good food" "o") @result{} ("S" "up is g" "" "d f" "" "d") @@ -354,15 +361,6 @@ practice: (split-string "ooo" "\\|o+" t) @result{} ("o" "o" "o") @end example - -If the optional argument @var{trim} is non-@code{nil}, it should be a -regular expression to match text to trim from the beginning and end of -each substring. If trimming makes the substring empty, it is treated -as null. - -If you need to split a string into a list of individual command-line -arguments suitable for @code{call-process} or @code{start-process}, -see @ref{Shell Arguments, split-string-and-unquote}. @end defun @defvar split-string-default-separators commit 4b04d8a7d550b9d4a0e83334c80b97d6e8a60ca2 Merge: b43c4616cc 45944e0183 Author: Eli Zaretskii Date: Fri May 19 14:36:43 2017 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit b43c4616ccc9cbaf7bc1531d0e6a4a84227f339e Author: Ruslan Bekenev Date: Fri May 19 14:35:47 2017 +0300 Fix typos in doc strings * lisp/mail/rfc2231.el (rfc2231-encode-string): * lisp/mail/rfc2047.el (rfc2047-encode-parameter): * lisp/mail/rfc2045.el (rfc2045-encode-string): Fix typos in doc strings. (Bug#26103) diff --git a/lisp/mail/rfc2045.el b/lisp/mail/rfc2045.el index f6000500e1..11a6151887 100644 --- a/lisp/mail/rfc2045.el +++ b/lisp/mail/rfc2045.el @@ -28,7 +28,7 @@ (require 'ietf-drums) (defun rfc2045-encode-string (param value) - "Return and PARAM=VALUE string encoded according to RFC2045." + "Return a PARAM=VALUE string encoded according to RFC2045." (if (or (string-match (concat "[" ietf-drums-no-ws-ctl-token "]") value) (string-match (concat "[" ietf-drums-tspecials "]") value) (string-match "[ \n\t]" value) diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el index bcbdc17631..d276e2117f 100644 --- a/lisp/mail/rfc2047.el +++ b/lisp/mail/rfc2047.el @@ -851,7 +851,7 @@ Point moves to the end of the region." (buffer-string))) (defun rfc2047-encode-parameter (param value) - "Return and PARAM=VALUE string encoded in the RFC2047-like style. + "Return a PARAM=VALUE string encoded in the RFC2047-like style. This is a substitution for the `rfc2231-encode-string' function, that is the standard but many mailers don't support it." (let ((rfc2047-encoding-type 'mime) diff --git a/lisp/mail/rfc2231.el b/lisp/mail/rfc2231.el index ba972c7346..66f539f698 100644 --- a/lisp/mail/rfc2231.el +++ b/lisp/mail/rfc2231.el @@ -234,7 +234,7 @@ These look like: (decode-coding-string (buffer-string) coding-system))))) (defun rfc2231-encode-string (param value) - "Return and PARAM=VALUE string encoded according to RFC2231. + "Return a PARAM=VALUE string encoded according to RFC2231. Use `mml-insert-parameter' or `mml-insert-parameter-string' to insert the result of this function." (let ((control (ietf-drums-token-to-list ietf-drums-no-ws-ctl-token)) commit 45944e0183af5b6a2e31248a815fb061f9757eed Author: Philipp Stephani Date: Fri May 19 13:26:29 2017 +0200 Fix module tests on some systems If dladdr(3) isn't available or didn't work, the printed representation of a module function will not include the file name, but only the address. Make the tests pass in that case. * test/src/emacs-module-tests.el (module-function-object): Fix match for module function printed representation diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el index eb7c82b2f6..0f4bfae00a 100644 --- a/test/src/emacs-module-tests.el +++ b/test/src/emacs-module-tests.el @@ -78,13 +78,11 @@ changes." (let ((obj (nth 2 body))) (should (equal (type-of obj) 'module-function)) (should (string-match-p - (rx (or "#") + (rx "#") (prin1-to-string obj))))))) ;; commit c189986b241cbe79b0e027fa08bba710ac645bb3 Author: Jean-Christophe Helary Date: Fri May 19 14:27:10 2017 +0300 Add an optional arguments to string-trim * lisp/emacs-lisp/subr-x.el (string-trim-left, string-trim-right) (string-trim): Add optional args that serve as defaults per the original behavior. (Bug#26908) diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 8a955277fe..849ac19d6a 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -178,21 +178,27 @@ VARLIST can just be a plain tuple. (define-obsolete-function-alias 'string-reverse 'reverse "25.1") -(defsubst string-trim-left (string) - "Remove leading whitespace from STRING." - (if (string-match "\\`[ \t\n\r]+" string) +(defsubst string-trim-left (string &optional regexp) + "Trim STRING of leading string matching REGEXP. + +REGEXP defaults to \"[ \\t\\n\\r]+\"." + (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+")"\\)") string) (replace-match "" t t string) string)) -(defsubst string-trim-right (string) - "Remove trailing whitespace from STRING." - (if (string-match "[ \t\n\r]+\\'" string) +(defsubst string-trim-right (string &optional regexp) + "Trim STRING of trailing string matching REGEXP. + +REGEXP defaults to \"[ \\t\\n\\r]+\"." + (if (string-match (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'") string) (replace-match "" t t string) string)) -(defsubst string-trim (string) - "Remove leading and trailing whitespace from STRING." - (string-trim-left (string-trim-right string))) +(defsubst string-trim (string &optional trim-left trim-right) + "Trim STRING of leading and trailing strings matching TRIM-LEFT and TRIM-RIGHT. + +TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"." + (string-trim-left (string-trim-right string trim-right) trim-left)) (defsubst string-blank-p (string) "Check whether STRING is either empty or only whitespace." commit cecd99d826547d4bfd918bba476eda206f0f0afc Author: Stephen Berman Date: Fri May 19 11:36:01 2017 +0200 Fix typo in last change to auto-hscroll-mode * lisp/cus-start.el (standard): Fix typo in value of auto-hscroll-mode. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index e11f749556..4253d40b75 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -563,7 +563,7 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Scroll the entire window" :value t) (const :tag "Scroll only the current line" - :value 'current-line)) + :value current-line)) "26.1") (void-text-area-pointer cursor (choice commit 7430617d3d84dc111e1a28f4f3884bf827d4fec9 Author: Eli Zaretskii Date: Fri May 19 11:51:16 2017 +0300 Support remote editing in emacsclient via Tramp * lib-src/emacsclient.c (main, decode_options) (print_help_and_exit, longopts): New option '--tramp' / '-T' which specifies how emacs should use tramp to find remote files. * doc/emacs/misc.texi (TCP Emacs server): New subsection describing the various knobs to tune server.el for TCP opereation. (emacsclient Options): Reference "TCP Emacs server" from description of --server-file. Document the new '--tramp' / '-T' options. * doc/emacs/emacs.texi (Top): Update the top-level menu. * etc/NEWS: Mention the new option. diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 5c8977c6b0..a3eb4225a7 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -1082,6 +1082,7 @@ Shell Command History Using Emacs as a Server +* TCP Emacs server:: Listening to a TCP socket. * Invoking emacsclient:: Connecting to the Emacs server. * emacsclient Options:: Emacs client startup options. diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index bcc20a6db1..84681f2269 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1661,10 +1661,68 @@ expression @code{(+ 1 2)} on the @samp{foo} server, and returns signaled.) Currently, this feature is mainly useful for developers. @menu +* TCP Emacs server:: Listening to a TCP socket. * Invoking emacsclient:: Connecting to the Emacs server. * emacsclient Options:: Emacs client startup options. @end menu +@node TCP Emacs server +@subsection TCP Emacs server +@cindex TCP Emacs server + +@vindex server-use-tcp + An Emacs server usually listens to connections on a local Unix +domain socket. Some operating systems, such as MS-Windows, do not +support local sockets; in that case, the server uses TCP sockets +instead. In some cases it is useful to have the server listen on a +TCP socket even if local sockets are supported, e.g., if you need to +contact the Emacs server from a remote machine. You can set +@code{server-use-tcp} to non-@code{nil} to have Emacs listen on a TCP +socket instead of a local socket. This is the default if your OS does +not support local sockets. + +@vindex server-host +@vindex server-port + If the Emacs server is set to use TCP, it will by default listen to +a random port on the localhost interface. This can be changed to +another interface and/or a fixed port using the variables +@code{server-host} and @code{server-port}. + +@vindex server-auth-key + A TCP socket is not subject to file system permissions. To retain +some control over which users can talk to an Emacs server over TCP +sockets, the @command{emacsclient} program must send an authorization +key to the server. This key is normally randomly generated by the +Emacs server. This is the recommended mode of operation. + +@findex server-generate-key + If needed, you can set the authorization key to a static value by +setting the @code{server-auth-key} variable. The key must consist of +64 ASCII printable characters except for space (this means characters +from @samp{!} to @samp{~}, or from decimal code 33 to 126). You can +use @kbd{M-x server-generate-key} to get a random key. + +@vindex server-auth-dir +@cindex server file + When you start a TCP Emacs server, Emacs creates a @dfn{server file} +containing the TCP information to be used by @command{emacsclient} to +connect to the server. The variable @code{server-auth-dir} specifies +the directory containing the server file; by default, this is +@file{~/.emacs.d/server/}. In the absence of a local socket with file +permissions, the permissions of this directory determine which users +can have their @command{emacsclient} processes talk to the Emacs +server. + +@vindex EMACS_SERVER_FILE@r{, environment variable} + To tell @command{emacsclient} to connect to the server over TCP with +a specific server file, use the @samp{-f} or @samp{--server-file} +option, or set the @env{EMACS_SERVER_FILE} environment variable +(@pxref{emacsclient Options}). If @code{server-auth-dir} is set to a +non-standard value, @command{emacsclient} needs an absolute file name +to the server file, as the default @code{server-auth-dir} is +hard-coded in @command{emacsclient} to be used as the directory for +resolving relative filenames. + @node Invoking emacsclient @subsection Invoking @code{emacsclient} @cindex @code{emacsclient} invocation @@ -1810,25 +1868,18 @@ evaluate, @emph{not} as a list of files to visit. @item -f @var{server-file} @itemx --server-file=@var{server-file} -@cindex @env{EMACS_SERVER_FILE} environment variable -Specify a @dfn{server file} for connecting to an Emacs server via TCP. - -An Emacs server usually uses a -local socket to listen for connections. Some operating systems, -such as Microsoft Windows, do not support local sockets; in that case, -the server communicates with @command{emacsclient} via TCP. - -@vindex server-auth-dir -@cindex server file -@vindex server-port -When you start a TCP Emacs server, Emacs creates a @dfn{server file} -containing the TCP information to be used by @command{emacsclient} to -connect to the server. The variable @code{server-auth-dir} specifies -the directory containing the server file; by default, this is -@file{~/.emacs.d/server/}. To tell @command{emacsclient} to connect -to the server over TCP with a specific server file, use the @samp{-f} -or @samp{--server-file} option, or set the @env{EMACS_SERVER_FILE} -environment variable. +Specify a server file (@pxref{TCP Emacs server}) for connecting to an +Emacs server via TCP. Alternatively, you can set the +@env{EMACS_SERVER_FILE} environment variable to point to the server +file. + +An Emacs server usually uses a local socket to listen for connections, +but also supports connections over TCP. To connect to a TCP Emacs +server, @command{emacsclient} needs to read a @dfn{server file} +containing the connection details of the Emacs server. The name of +this file is specified with this option, either as a file name +relative to @file{~/.emacs.d/server} or as an absolute file name. +@xref{TCP Emacs server}. @item -n @itemx --no-wait @@ -1872,6 +1923,37 @@ On MS-Windows, @samp{-t} behaves just like @samp{-c} if the Emacs server is using the graphical display, but if the Emacs server is running on a text terminal, it creates a new frame in the current text terminal. + +@item -T @var{tramp-prefix} +@itemx --tramp-prefix=@var{tramp-prefix} +Set the prefix to add to filenames for Emacs to locate files on remote +machines using TRAMP (@pxref{Top, The Tramp Manual,, tramp, The Tramp +Manual}). This is mostly useful in combination with using the Emacs +server over TCP (@pxref{TCP Emacs server}). By ssh-forwarding the +listening port and making the @var{server-file} available on a remote +machine, programs on the remote machine can use @command{emacsclient} +as the value for the @env{EDITOR} and similar environment variables, +but instead of talking to an Emacs server on the remote machine, the +files will be visited in the local Emacs session using TRAMP. + +@vindex EMACSCLIENT_TRAMP@r{, environment variable} +Setting the environment variable @env{EMACSCLIENT_TRAMP} has the same +effect as using the @samp{-T} option. If both are specified, the +command-line option takes precedence. + +For example, assume two hosts, @samp{local} and @samp{remote}, and +that the local Emacs listens on tcp port 12345. Assume further that +@file{/home} is on a shared file system, so that the server file +@file{~/.emacs.d/server/server} is readable on both hosts. + +@example +local$ ssh -R12345:localhost:12345 remote +remote$ export EDITOR="emacsclient \ + --server-file=server \ + --tramp=/ssh:remote:" +remote$ $EDITOR /tmp/foo.txt #Should open in local emacs. +@end example + @end table The new graphical or text terminal frames created by the @samp{-c} diff --git a/etc/NEWS b/etc/NEWS index 4121c44b0c..340718ecbc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -344,6 +344,14 @@ for DNS-querying functions 'nslookup-host', 'dns-lookup-host', and 'run-dig'. Each function now accepts an optional name server argument interactively (with a prefix argument) and non-interactively. ++++ +** Emacsclient has a new option -T/--tramp. +This helps with using a local Emacs session as the server for a remote +emacsclient. With appropriate setup, one can now set the EDITOR +environment variable on a remote machine to emacsclient, and +use the local Emacs to edit remote files via Tramp. See the node +"emacsclient Options" in the user manual for the details. + * Editing Changes in Emacs 26.1 diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 7b735dfb05..c21ee6bd39 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -149,6 +149,9 @@ const char *socket_name = NULL; /* If non-NULL, the filename of the authentication file. */ const char *server_file = NULL; +/* If non-NULL, the tramp prefix emacs must use to find the files. */ +const char *tramp_prefix = NULL; + /* PID of the Emacs server process. */ int emacs_pid = 0; @@ -178,6 +181,7 @@ struct option longopts[] = { "server-file", required_argument, NULL, 'f' }, { "display", required_argument, NULL, 'd' }, { "parent-id", required_argument, NULL, 'p' }, + { "tramp", required_argument, NULL, 'T' }, { 0, 0, 0, 0 } }; @@ -468,14 +472,15 @@ static void decode_options (int argc, char **argv) { alternate_editor = egetenv ("ALTERNATE_EDITOR"); + tramp_prefix = egetenv ("EMACSCLIENT_TRAMP"); while (1) { int opt = getopt_long_only (argc, argv, #ifndef NO_SOCKETS_IN_FILE_SYSTEM - "VHnequa:s:f:d:F:tc", + "VHnequa:s:f:d:F:tcT:", #else - "VHnequa:f:d:F:tc", + "VHnequa:f:d:F:tcT:", #endif longopts, 0); @@ -554,6 +559,10 @@ decode_options (int argc, char **argv) frame_parameters = optarg; break; + case 'T': + tramp_prefix = optarg; + break; + default: message (true, "Try '%s --help' for more information\n", progname); exit (EXIT_FAILURE); @@ -654,6 +663,9 @@ The following OPTIONS are accepted:\n\ Editor to fallback to if the server is not running\n" " If EDITOR is the empty string, start Emacs in daemon\n\ mode and try connecting again\n" +"-T PREFIX, --tramp=PREFIX\n\ + PREFIX to prepend to filenames sent by emacsclient\n\ + for locating files remotely via Tramp\n" "\n\ Report bugs with M-x report-emacs-bug.\n"); exit (EXIT_SUCCESS); @@ -1687,6 +1699,8 @@ main (int argc, char **argv) } } send_to_emacs (emacs_socket, "-dir "); + if (tramp_prefix) + quote_argument (emacs_socket, tramp_prefix); quote_argument (emacs_socket, cwd); send_to_emacs (emacs_socket, "/"); send_to_emacs (emacs_socket, " "); @@ -1791,6 +1805,8 @@ main (int argc, char **argv) #endif send_to_emacs (emacs_socket, "-file "); + if (tramp_prefix && file_name_absolute_p (argv[i])) + quote_argument (emacs_socket, tramp_prefix); quote_argument (emacs_socket, argv[i]); send_to_emacs (emacs_socket, " "); }