------------------------------------------------------------ revno: 117621 committer: Dmitry Antipov branch nick: trunk timestamp: Fri 2014-08-01 10:52:02 +0400 message: * atimer.c (toplevel) [HAVE_TIMERFD]: Include errno.h. (timerfd_callback): Ignore weird events with no data. Add tight assertions and comments. (init_atimer) [HAVE_TIMERFD]: Add environment variable to optionally disabletimerfd-based timer. Use TFD_NONBLOCK for timer descriptor. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2014-08-01 00:01:44 +0000 +++ src/ChangeLog 2014-08-01 06:52:02 +0000 @@ -1,3 +1,11 @@ +2014-08-01 Dmitry Antipov + + * atimer.c (toplevel) [HAVE_TIMERFD]: Include errno.h. + (timerfd_callback): Ignore weird events with no data. Add tight + assertions and comments. + (init_atimer) [HAVE_TIMERFD]: Add environment variable to optionally + disable timerfd-based timer. Use TFD_NONBLOCK for timer descriptor. + 2014-08-01 Paul Eggert * frame.c (x_set_frame_parameters): Fix typo in previous patch. === modified file 'src/atimer.c' --- src/atimer.c 2014-07-31 20:17:01 +0000 +++ src/atimer.c 2014-08-01 06:52:02 +0000 @@ -27,6 +27,7 @@ #include #ifdef HAVE_TIMERFD +#include # include #endif @@ -399,14 +400,26 @@ void timerfd_callback (int fd, void *arg) { - char buf[8]; ptrdiff_t nbytes; + uint64_t expirations; eassert (fd == timerfd); - nbytes = emacs_read (fd, buf, sizeof (buf)); - /* Just discard an expiration count for now. */ - eassert (nbytes == sizeof (buf)); - do_pending_atimers (); + nbytes = emacs_read (fd, &expirations, sizeof (expirations)); + + if (nbytes == sizeof (expirations)) + { + /* Timer should expire just once. */ + eassert (expirations == 1); + do_pending_atimers (); + } + else if (nbytes < 0) + /* For some not yet known reason, we may get weird event and no + data on timer descriptor. This can break Gnus at least, see: + http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00503.html. */ + eassert (errno == EAGAIN); + else + /* I don't know what else can happen with this descriptor. */ + emacs_abort (); } #endif /* HAVE_TIMERFD */ @@ -528,7 +541,9 @@ { #ifdef HAVE_ITIMERSPEC # ifdef HAVE_TIMERFD - timerfd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC); + /* Until this feature is considered stable, you can ask to not use it. */ + timerfd = (egetenv ("EMACS_IGNORE_TIMERFD") ? -1 : + timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC)); # endif if (timerfd < 0) { ------------------------------------------------------------ revno: 117620 committer: Fabi?n Ezequiel Gallina branch nick: trunk timestamp: Thu 2014-07-31 21:18:19 -0300 message: * lisp/progmodes/python.el: Shell output capture enhancements. (python-shell-accept-process-output): New function. (inferior-python-mode) (python-shell-send-setup-code): Use it. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2014-07-30 17:13:16 +0000 +++ lisp/ChangeLog 2014-08-01 00:18:19 +0000 @@ -1,3 +1,10 @@ +2014-07-31 Fabián Ezequiel Gallina + + * progmodes/python.el: Shell output capture enhancements. + (python-shell-accept-process-output): New function. + (inferior-python-mode) + (python-shell-send-setup-code): Use it. + 2014-07-30 Christophe Deleuze (tiny change) * calendar/icalendar.el (icalendar--decode-isodatetime): Use === modified file 'lisp/progmodes/python.el' --- lisp/progmodes/python.el 2014-07-28 21:07:10 +0000 +++ lisp/progmodes/python.el 2014-08-01 00:18:19 +0000 @@ -2129,6 +2129,27 @@ directory package package) (python-shell-get-process))) +(defun python-shell-accept-process-output (process &optional timeout regexp) + "Accept PROCESS output with TIMEOUT until REGEXP is found. +Optional argument TIMEOUT is the timeout argument to +`accept-process-output' calls. Optional argument REGEXP +overrides the regexp to match the end of output, defaults to +`comint-prompt-regexp.'. Returns non-nil when output was +properly captured. + +This utility is useful in situations where the output may be +received in chunks, since `accept-process-output' gives no +guarantees they will be grabbed in a single call. An example use +case for this would be the CPython shell start-up, where the +banner and the initial prompt are received separetely." + (let ((regexp (or regexp comint-prompt-regexp))) + (catch 'found + (while t + (when (not (accept-process-output process timeout)) + (throw 'found nil)) + (when (looking-back regexp) + (throw 'found t)))))) + (defun python-shell-comint-end-of-output-p (output) "Return non-nil if OUTPUT is ends with input prompt." (string-match @@ -2380,13 +2401,8 @@ (when python-shell-font-lock-enable (python-shell-font-lock-turn-on)) (compilation-shell-minor-mode 1) - ;; Ensure all the output is accepted before running any hooks. - (accept-process-output (get-buffer-process (current-buffer))) - ;; At this point, all process output should have been received, but - ;; on GNU/Linux, calling `python-shell-internal-send-string' without - ;; a running internal shell fails to grab output properly unless - ;; this `sit-for' is in place. - (sit-for 0.1 t)) + (python-shell-accept-process-output + (get-buffer-process (current-buffer)))) (defun python-shell-make-comint (cmd proc-name &optional pop internal) "Create a Python shell comint buffer. @@ -2790,8 +2806,8 @@ python-shell-setup-codes "\n\n") "\n\nprint ('python.el: sent setup code')"))) - (python-shell-send-string code) - (accept-process-output process))) + (python-shell-send-string code process) + (python-shell-accept-process-output process))) (add-hook 'inferior-python-mode-hook #'python-shell-send-setup-code) ------------------------------------------------------------ revno: 117619 author: Tassilo Horn committer: Katsumi Yamaoka branch nick: trunk timestamp: Fri 2014-08-01 00:10:16 +0000 message: doc/misc/ChangeLog: Add missing entry for gnus.texi diff: === modified file 'doc/misc/ChangeLog' --- doc/misc/ChangeLog 2014-07-28 09:39:09 +0000 +++ doc/misc/ChangeLog 2014-08-01 00:10:16 +0000 @@ -1,3 +1,8 @@ +2014-07-31 Tassilo Horn + + * gnus.texi (Group Parameters): Document that `gcc-self' may also be a + list. + 2014-07-28 Stephen Berman * todo-mode.texi (Marked Items): Correct omission of item deletion ------------------------------------------------------------ revno: 117618 committer: Paul Eggert branch nick: trunk timestamp: Thu 2014-07-31 17:04:52 -0700 message: Minor style fix to previous patch. diff: === modified file 'src/frame.c' --- src/frame.c 2014-08-01 00:01:44 +0000 +++ src/frame.c 2014-08-01 00:04:52 +0000 @@ -3198,9 +3198,9 @@ XSETFRAME (frame, f); - if (((width_change && width != FRAME_TEXT_WIDTH (f)) - || (height_change && height != FRAME_TEXT_HEIGHT (f))) - || f->new_height || f->new_width) + if ((width_change && width != FRAME_TEXT_WIDTH (f)) + || (height_change && height != FRAME_TEXT_HEIGHT (f)) + || f->new_height || f->new_width) { /* If necessary provide default values for HEIGHT and WIDTH. Do that here since otherwise a size change implied by an ------------------------------------------------------------ revno: 117617 committer: Paul Eggert branch nick: trunk timestamp: Thu 2014-07-31 17:01:44 -0700 message: * frame.c (x_set_frame_parameters): Fix typo in previous patch. I had confused && with ||. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2014-07-31 20:17:01 +0000 +++ src/ChangeLog 2014-08-01 00:01:44 +0000 @@ -1,3 +1,8 @@ +2014-08-01 Paul Eggert + + * frame.c (x_set_frame_parameters): Fix typo in previous patch. + I had confused && with ||. + 2014-07-31 Paul Eggert Simplify timerfd configuration and fix some minor glitches. === modified file 'src/frame.c' --- src/frame.c 2014-07-31 13:55:12 +0000 +++ src/frame.c 2014-08-01 00:01:44 +0000 @@ -3200,7 +3200,7 @@ if (((width_change && width != FRAME_TEXT_WIDTH (f)) || (height_change && height != FRAME_TEXT_HEIGHT (f))) - && (f->new_height || f->new_width)) + || f->new_height || f->new_width) { /* If necessary provide default values for HEIGHT and WIDTH. Do that here since otherwise a size change implied by an ------------------------------------------------------------ revno: 117616 committer: Paul Eggert branch nick: trunk timestamp: Thu 2014-07-31 13:17:01 -0700 message: Simplify timerfd configuration and fix some minor glitches. * configure.ac (HAVE_TIMERFD): Define only if TFD_CLOEXEC works, since the code leaked file descriptors to children when !TFD_CLOEXEC. (HAVE_TIMERFD_CLOEXEC): Remove; no longer used. * m4/clock_time.m4 (gl_CLOCK_TIME): Don't check for clock_getres. This reverts the previous change to this file, so it matches gnulib again. * src/atimer.c (TIMERFD_CREATE_FLAGS): Remove; we now assume TFD_CLOEXEC. (alarm_timer, alarm_timer_ok, set_alarm, init_atimer): Fall back on timer_create if timerfd_create fails at runtime. (resolution) [HAVE_CLOCK_GETRES]: Remove; we now rely on the kernel primitives to do resolution. All uses removed. (timerfd) [!HAVE_TIMERFD]: Define to be -1, for convenience. (turn_on_atimers): Clear timer_create-based timers too, for consistency. diff: === modified file 'ChangeLog' --- ChangeLog 2014-07-28 06:28:15 +0000 +++ ChangeLog 2014-07-31 20:17:01 +0000 @@ -1,3 +1,13 @@ +2014-07-31 Paul Eggert + + Simplify timerfd configuration and fix some minor glitches. + * configure.ac (HAVE_TIMERFD): Define only if TFD_CLOEXEC works, + since the code leaked file descriptors to children when !TFD_CLOEXEC. + (HAVE_TIMERFD_CLOEXEC): Remove; no longer used. + * m4/clock_time.m4 (gl_CLOCK_TIME): Don't check for clock_getres. + This reverts the previous change to this file, so it matches + gnulib again. + 2014-07-28 Dmitry Antipov * configure.ac (toplevel): Check whether GNU/Linux-specific === modified file 'configure.ac' --- configure.ac 2014-07-28 06:28:15 +0000 +++ configure.ac 2014-07-31 20:17:01 +0000 @@ -1539,7 +1539,7 @@ AC_DEFINE(LINUX_SYSINFO_UNIT, 1, [Define to 1 if Linux sysinfo sizes are in multiples of mem_unit bytes.])) fi -fi +fi dnl On Solaris 8 there's a compilation warning for term.h because dnl it doesn't define `bool'. @@ -3711,25 +3711,18 @@ AC_SUBST(TERMCAP_OBJ) # GNU/Linux-specific timer functions. -if test $opsys = gnu-linux; then - AC_MSG_CHECKING([whether Linux timerfd functions are supported]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[timerfd_create (CLOCK_REALTIME, 0); - timerfd_settime (0, 0, NULL, NULL)]])], - emacs_cv_linux_timerfd=yes, emacs_cv_linux_timerfd=no) - AC_MSG_RESULT([$emacs_cv_linux_timerfd]) - if test $emacs_cv_linux_timerfd = yes; then - AC_DEFINE(HAVE_TIMERFD, 1, [Define to 1 if Linux timerfd functions are supported.]) - AC_MSG_CHECKING([whether TFD_CLOEXEC is defined]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC)]])], - emacs_cv_tfd_cloexec=yes, emacs_cv_tfd_cloexec=no) - AC_MSG_RESULT([$emacs_cv_tfd_cloexec]) - if test $emacs_cv_tfd_cloexec = yes; then - AC_DEFINE(HAVE_TIMERFD_CLOEXEC, 1, [Define to 1 if TFD_CLOEXEC is defined.]) - fi - fi -fi +AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include + ]], + [[timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC); + timerfd_settime (0, TFD_TIMER_ABSTIME, 0, 0);]])], + [emacs_cv_have_timerfd=yes], + [emacs_cv_have_timerfd=no])]) +if test "$emacs_cv_have_timerfd" = yes; then + AC_DEFINE([HAVE_TIMERFD], 1, + [Define to 1 if timerfd functions are supported as in GNU/Linux.]) +fi # Do we have res_init, for detecting changes in /etc/resolv.conf? # On Darwin, res_init appears not to be useful: see bug#562 and === modified file 'm4/clock_time.m4' --- m4/clock_time.m4 2014-07-28 06:28:15 +0000 +++ m4/clock_time.m4 2014-07-31 20:17:01 +0000 @@ -26,6 +26,6 @@ AC_SEARCH_LIBS([clock_gettime], [rt posix4], [test "$ac_cv_search_clock_gettime" = "none required" || LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime]) - AC_CHECK_FUNCS([clock_getres clock_gettime clock_settime]) + AC_CHECK_FUNCS([clock_gettime clock_settime]) LIBS=$gl_saved_libs ]) === modified file 'src/ChangeLog' --- src/ChangeLog 2014-07-31 13:55:12 +0000 +++ src/ChangeLog 2014-07-31 20:17:01 +0000 @@ -1,5 +1,15 @@ 2014-07-31 Paul Eggert + Simplify timerfd configuration and fix some minor glitches. + * atimer.c (TIMERFD_CREATE_FLAGS): Remove; we now assume TFD_CLOEXEC. + (alarm_timer, alarm_timer_ok, set_alarm, init_atimer): + Fall back on timer_create if timerfd_create fails at runtime. + (resolution) [HAVE_CLOCK_GETRES]: Remove; we now rely on the + kernel primitives to do resolution. All uses removed. + (timerfd) [!HAVE_TIMERFD]: Define to be -1, for convenience. + (turn_on_atimers): Clear timer_create-based timers too, + for consistency. + * frame.c (x_set_frame_parameters): Don't use uninitialized locals. Without this change, the code can access the local variable 'width' even when it has not been initialized, and likewise for 'height'; === modified file 'src/atimer.c' --- src/atimer.c 2014-07-28 14:50:55 +0000 +++ src/atimer.c 2014-07-31 20:17:01 +0000 @@ -27,13 +27,8 @@ #include #ifdef HAVE_TIMERFD -#include -#ifdef HAVE_TIMERFD_CLOEXEC -#define TIMERFD_CREATE_FLAGS TFD_CLOEXEC -#else -#define TIMERFD_CREATE_FLAGS 0 -#endif /* HAVE_TIMERFD_CLOEXEC */ -#endif /* HAVE_TIMERFD */ +# include +#endif /* Free-list of atimer structures. */ @@ -49,23 +44,18 @@ static struct atimer *atimers; -#if defined (HAVE_TIMERFD) -/* File descriptor returned by timerfd_create. GNU/Linux-specific. */ +#ifdef HAVE_ITIMERSPEC +/* The alarm timer and whether it was properly initialized, if + POSIX timers are available. */ +static timer_t alarm_timer; +static bool alarm_timer_ok; + +# ifdef HAVE_TIMERFD +/* File descriptor for timer, or -1 if it could not be created. */ static int timerfd; -#elif defined (HAVE_ITIMERSPEC) -/* The alarm timer used if POSIX timers are available. */ -static timer_t alarm_timer; -#endif - -#if defined (HAVE_TIMERFD) || defined (HAVE_ITIMERSPEC) -/* Non-zero if one of the above was successfully initialized. Do not - use bool due to special treatment if HAVE_TIMERFD, see below. */ -static int special_timer_available; -#endif - -#ifdef HAVE_CLOCK_GETRES -/* Resolution of CLOCK_REALTIME clock. */ -static struct timespec resolution; +# else +enum { timerfd = -1 }; +# endif #endif /* Block/unblock SIGALRM. */ @@ -92,20 +82,20 @@ static struct atimer *append_atimer_lists (struct atimer *, struct atimer *); -/* Start a new atimer of type TYPE. TIME specifies when the timer is +/* Start a new atimer of type TYPE. TIMESTAMP specifies when the timer is ripe. FN is the function to call when the timer fires. CLIENT_DATA is stored in the client_data member of the atimer structure returned and so made available to FN when it is called. - If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the + If TYPE is ATIMER_ABSOLUTE, TIMESTAMP is the absolute time at which the timer fires. - If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the + If TYPE is ATIMER_RELATIVE, the timer is ripe TIMESTAMP seconds in the future. In both cases, the timer is automatically freed after it has fired. - If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us. + If TYPE is ATIMER_CONTINUOUS, the timer fires every TIMESTAMP seconds. Value is a pointer to the atimer started. It can be used in calls to cancel_atimer; don't free it yourself. */ @@ -117,16 +107,10 @@ struct atimer *t; sigset_t oldset; -#if !defined (HAVE_SETITIMER) - /* Round TIME up to the next full second if we don't have itimers. */ + /* Round TIMESTAMP up to the next full second if we don't have itimers. */ +#ifndef HAVE_SETITIMER if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t)) timestamp = make_timespec (timestamp.tv_sec + 1, 0); -#elif defined (HAVE_CLOCK_GETRES) - /* Check that the system clock is precise enough. If - not, round TIME up to the system clock resolution. */ - if (timespec_valid_p (resolution) - && timespec_cmp (timestamp, resolution) < 0) - timestamp = resolution; #endif /* not HAVE_SETITIMER */ /* Get an atimer structure from the free-list, or allocate @@ -311,25 +295,24 @@ #endif struct timespec now, interval; -#if defined (HAVE_TIMERFD) || defined (HAVE_ITIMERSPEC) - if (special_timer_available) +#ifdef HAVE_ITIMERSPEC + if (0 <= timerfd || alarm_timer_ok) { struct itimerspec ispec; ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; -#if defined (HAVE_TIMERFD) - if (special_timer_available == 1) +# ifdef HAVE_TIMERFD + if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) { add_timer_wait_descriptor (timerfd); - special_timer_available++; + return; } - if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) -#elif defined (HAVE_ITIMERSPEC) - if (timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) -#endif +# endif + if (alarm_timer_ok + && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) return; } -#endif /* HAVE_TIMERFD || HAVE_ITIMERSPEC */ +#endif /* Determine interval till the next timer is ripe. Don't set the interval to 0; this disables the timer. */ @@ -453,15 +436,15 @@ set_alarm (); else { -#ifdef HAVE_TIMERFD - if (special_timer_available > 1) - { - struct itimerspec ispec; - memset (&ispec, 0, sizeof (ispec)); - /* Writing zero expiration time should disarm it. */ - timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); - } -#endif /* HAVE_TIMERFD */ +#ifdef HAVE_ITIMERSPEC + struct itimerspec ispec; + memset (&ispec, 0, sizeof ispec); + if (alarm_timer_ok) + timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0); +# ifdef HAVE_TIMERFD + timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); +# endif +#endif alarm (0); } } @@ -494,14 +477,14 @@ r->intime = 0; else if (result >= 0) { -#ifdef HAVE_SETITIMER +#ifdef HAVE_SETITIMER struct timespec delta = timespec_sub (now, r->expected); /* Too late if later than expected + 0.01s. FIXME: this should depend from system clock resolution. */ if (timespec_cmp (delta, make_timespec (0, 10000000)) > 0) r->intime = 0; else -#endif /* HAVE_SETITIMER */ +#endif /* HAVE_SETITIMER */ r->intime = 1; } } @@ -543,21 +526,20 @@ void init_atimer (void) { -#if defined (HAVE_TIMERFD) - timerfd = timerfd_create (CLOCK_REALTIME, TIMERFD_CREATE_FLAGS); - special_timer_available = !!(timerfd != -1); -#elif defined (HAVE_ITIMERSPEC) - struct sigevent sigev; - sigev.sigev_notify = SIGEV_SIGNAL; - sigev.sigev_signo = SIGALRM; - sigev.sigev_value.sival_ptr = &alarm_timer; - special_timer_available - = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; -#endif /* HAVE_TIMERFD */ -#ifdef HAVE_CLOCK_GETRES - if (clock_getres (CLOCK_REALTIME, &resolution)) - resolution = invalid_timespec (); -#endif +#ifdef HAVE_ITIMERSPEC +# ifdef HAVE_TIMERFD + timerfd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC); +# endif + if (timerfd < 0) + { + struct sigevent sigev; + sigev.sigev_notify = SIGEV_SIGNAL; + sigev.sigev_signo = SIGALRM; + sigev.sigev_value.sival_ptr = &alarm_timer; + alarm_timer_ok + = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; + } +#endif free_atimers = stopped_atimers = atimers = NULL; /* pending_signals is initialized in init_keyboard. */ @@ -567,5 +549,5 @@ #ifdef ENABLE_CHECKING defsubr (&Sdebug_timer_check); -#endif +#endif } ------------------------------------------------------------ revno: 117615 committer: Paul Eggert branch nick: trunk timestamp: Thu 2014-07-31 06:55:12 -0700 message: * frame.c (x_set_frame_parameters): Don't use uninitialized locals. Without this change, the code can access the local variable 'width' even when it has not been initialized, and likewise for 'height'; in either case this leads to undefined behavior. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2014-07-30 04:03:45 +0000 +++ src/ChangeLog 2014-07-31 13:55:12 +0000 @@ -1,3 +1,10 @@ +2014-07-31 Paul Eggert + + * frame.c (x_set_frame_parameters): Don't use uninitialized locals. + Without this change, the code can access the local variable 'width' + even when it has not been initialized, and likewise for 'height'; + in either case this leads to undefined behavior. + 2014-07-30 Dmitry Antipov * xrdb.c (x_load_resources) [USE_MOTIF]: Although not strictly === modified file 'src/frame.c' --- src/frame.c 2014-07-29 08:51:49 +0000 +++ src/frame.c 2014-07-31 13:55:12 +0000 @@ -3198,10 +3198,9 @@ XSETFRAME (frame, f); - if ((width_change || height_change) - && (width != FRAME_TEXT_WIDTH (f) - || height != FRAME_TEXT_HEIGHT (f) - || f->new_height || f->new_width)) + if (((width_change && width != FRAME_TEXT_WIDTH (f)) + || (height_change && height != FRAME_TEXT_HEIGHT (f))) + && (f->new_height || f->new_width)) { /* If necessary provide default values for HEIGHT and WIDTH. Do that here since otherwise a size change implied by an ------------------------------------------------------------ revno: 117614 author: Tassilo Horn committer: Katsumi Yamaoka branch nick: trunk timestamp: Thu 2014-07-31 13:11:41 +0000 message: [Gnus] Allow list-valued gcc-self group params * lisp/gnus/gnus-msg.el (gnus-inews-insert-gcc): Allow `gcc-self' to be a list of groups and t. * doc/misc/gnus.texi (Group Parameters): Document that `gcc-self' may also be a list. diff: === modified file 'doc/misc/gnus.texi' --- doc/misc/gnus.texi 2014-07-18 08:23:49 +0000 +++ doc/misc/gnus.texi 2014-07-31 13:11:41 +0000 @@ -2880,12 +2880,17 @@ @item gcc-self @cindex gcc-self If @code{(gcc-self . t)} is present in the group parameter list, newly -composed messages will be @code{Gcc}'d to the current group. If +composed messages will be @code{gcc}d to the current group. If @code{(gcc-self . none)} is present, no @code{Gcc:} header will be -generated, if @code{(gcc-self . "string")} is present, this string will -be inserted literally as a @code{gcc} header. This parameter takes -precedence over any default @code{Gcc} rules as described later -(@pxref{Archived Messages}), with the exception for messages to resend. +generated, if @code{(gcc-self . "group")} is present, this string will +be inserted literally as a @code{Gcc:} header. It should be a group +name. The @code{gcc-self} value may also be a list of strings and +@code{t}, e.g., @code{(gcc-self "group1" "group2" t)} means to +@code{gcc} the newly composed message into the groups @code{"group1"} +and @code{"group2"}, and into the current group. The @code{gcc-self} +parameter takes precedence over any default @code{Gcc} rules as +described later (@pxref{Archived Messages}), with the exception for +messages to resend. @strong{Caveat}: Adding @code{(gcc-self . t)} to the parameter list of @code{nntp} groups (or the like) isn't valid. An @code{nntp} server === modified file 'lisp/gnus/gnus-msg.el' --- lisp/gnus/gnus-msg.el 2014-07-18 08:23:49 +0000 +++ lisp/gnus/gnus-msg.el 2014-07-31 13:11:41 +0000 @@ -1726,7 +1726,20 @@ (var (or gnus-outgoing-message-group gnus-message-archive-group)) (gcc-self-val (and group (not (gnus-virtual-group-p group)) - (gnus-group-find-parameter group 'gcc-self))) + (gnus-group-find-parameter group 'gcc-self t))) + (gcc-self-get (lambda (gcc-self-val group) + (if (stringp gcc-self-val) + (if (string-match " " gcc-self-val) + (concat "\"" gcc-self-val "\"") + gcc-self-val) + ;; In nndoc groups, we use the parent group name + ;; instead of the current group. + (let ((group (or (gnus-group-find-parameter + gnus-newsgroup-name 'parent-group) + group))) + (if (string-match " " group) + (concat "\"" group "\"") + group))))) result (groups (cond @@ -1777,19 +1790,11 @@ (if gcc-self-val ;; Use the `gcc-self' param value instead. (progn - (insert - (if (stringp gcc-self-val) - (if (string-match " " gcc-self-val) - (concat "\"" gcc-self-val "\"") - gcc-self-val) - ;; In nndoc groups, we use the parent group name - ;; instead of the current group. - (let ((group (or (gnus-group-find-parameter - gnus-newsgroup-name 'parent-group) - group))) - (if (string-match " " group) - (concat "\"" group "\"") - group)))) + (insert (if (listp gcc-self-val) + (mapconcat (lambda (val) + (funcall gcc-self-get val group)) + gcc-self-val ", ") + (funcall gcc-self-get gcc-self-val group))) (if (not (eq gcc-self-val 'none)) (insert "\n") (gnus-delete-line))) ------------------------------------------------------------ revno: 117613 committer: Glenn Morris branch nick: trunk timestamp: Wed 2014-07-30 13:13:16 -0400 message: ChangeLog fix diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2014-07-30 16:25:58 +0000 +++ lisp/ChangeLog 2014-07-30 17:13:16 +0000 @@ -1,4 +1,4 @@ -2014-07-30 Christophe Deleuze +2014-07-30 Christophe Deleuze (tiny change) * calendar/icalendar.el (icalendar--decode-isodatetime): Use actual current-time-zone when converting to local time. (Bug#15408)