Now on revision 113296. ------------------------------------------------------------ revno: 113296 committer: Paul Eggert branch nick: trunk timestamp: Fri 2013-07-05 19:40:50 -0700 message: Use emacs_open more consistently when opening files. This handles EINTR more consistently now, and makes it easier to introduce other uniform changes to file descriptor handling. * src/systdio.h: New file. * src/buffer.c (mmap_init): * cygw32.c (chdir_to_default_directory): * dispnew.c (Fopen_termscript): * emacs.c (Fdaemon_initialized): * fileio.c (Fdo_auto_save): * image.c (slurp_file, png_load_body, jpeg_load_body): * keyboard.c (Fopen_dribble_file): * lread.c (Fload): * print.c (Fredirect_debugging_output): * sysdep.c (get_up_time, procfs_ttyname, procfs_get_total_memory): * termcap.c (tgetent): * unexaix.c, unexcoff.c (unexec, adjust_lnnoptrs): * unexcw.c, unexelf.c, unexhp9k800.c, unexmacosx.c (unexec): * w32term.c (w32_initialize) [CYGWIN]: * xfaces.c (Fx_load_color_file): Use emacs_open instead of plain open, and emacs_fopen instead of plain fopen. * dispnew.c, fileio.c, image.c, keyboard.c, lread.c, print.c, sysdep.c: * xfaces.c: Include sysstdio.h rather than stdio.h, for emacs_fopen. * callproc.c (default_output_mode): New constant. (Fcall_process): Use it to call emacs_open instead of plain creat. * dispnew.c (Fopen_termscript): Fix minor race in opening termscript. * sysdep.c (emacs_open): Add commentary and don't call file name "path". (emacs_fopen): New function. * unexaix.c, unexcoff.c, unexelf.c, unexhp9k800.c, unexmacosx.c: Include , for emacs_open. * unexelf.c (fatal): Remove decl; not needed with included. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-07-05 16:58:01 +0000 +++ src/ChangeLog 2013-07-06 02:40:50 +0000 @@ -1,5 +1,37 @@ 2013-07-05 Paul Eggert + Use emacs_open more consistently when opening files. + This handles EINTR more consistently now, and makes it easier + to introduce other uniform changes to file descriptor handling. + * src/systdio.h: New file. + * src/buffer.c (mmap_init): + * cygw32.c (chdir_to_default_directory): + * dispnew.c (Fopen_termscript): + * emacs.c (Fdaemon_initialized): + * fileio.c (Fdo_auto_save): + * image.c (slurp_file, png_load_body, jpeg_load_body): + * keyboard.c (Fopen_dribble_file): + * lread.c (Fload): + * print.c (Fredirect_debugging_output): + * sysdep.c (get_up_time, procfs_ttyname, procfs_get_total_memory): + * termcap.c (tgetent): + * unexaix.c, unexcoff.c (unexec, adjust_lnnoptrs): + * unexcw.c, unexelf.c, unexhp9k800.c, unexmacosx.c (unexec): + * w32term.c (w32_initialize) [CYGWIN]: + * xfaces.c (Fx_load_color_file): + Use emacs_open instead of plain open, and emacs_fopen instead of + plain fopen. + * dispnew.c, fileio.c, image.c, keyboard.c, lread.c, print.c, sysdep.c: + * xfaces.c: Include sysstdio.h rather than stdio.h, for emacs_fopen. + * callproc.c (default_output_mode): New constant. + (Fcall_process): Use it to call emacs_open instead of plain creat. + * dispnew.c (Fopen_termscript): Fix minor race in opening termscript. + * sysdep.c (emacs_open): Add commentary and don't call file name "path". + (emacs_fopen): New function. + * unexaix.c, unexcoff.c, unexelf.c, unexhp9k800.c, unexmacosx.c: + Include , for emacs_open. + * unexelf.c (fatal): Remove decl; not needed with included. + Remove duplicate #include directives. * alloc.c [GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES]: * xfaces.c: === modified file 'src/buffer.c' --- src/buffer.c 2013-07-05 16:58:01 +0000 +++ src/buffer.c 2013-07-06 02:40:50 +0000 @@ -4726,7 +4726,7 @@ if (mmap_fd <= 0) { /* No anonymous mmap -- we need the file descriptor. */ - mmap_fd = open ("/dev/zero", O_RDONLY); + mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0); if (mmap_fd == -1) fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno)); } === modified file 'src/callproc.c' --- src/callproc.c 2013-06-27 14:47:52 +0000 +++ src/callproc.c 2013-07-06 02:40:50 +0000 @@ -186,6 +186,12 @@ return Qnil; } +#ifdef DOS_NT +static mode_t const default_output_mode = S_IREAD | S_IWRITE; +#else +static mode_t const default_output_mode = 0666; +#endif + DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0, doc: /* Call PROGRAM synchronously in separate process. The remaining arguments are optional. @@ -407,13 +413,9 @@ if (STRINGP (output_file)) { -#ifdef DOS_NT fd_output = emacs_open (SSDATA (output_file), - O_WRONLY | O_TRUNC | O_CREAT | O_TEXT, - S_IREAD | S_IWRITE); -#else /* not DOS_NT */ - fd_output = creat (SSDATA (output_file), 0666); -#endif /* not DOS_NT */ + O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, + default_output_mode); if (fd_output < 0) { output_file = DECODE_FILE (output_file); @@ -492,7 +494,8 @@ strcat (tempfile, "/"); strcat (tempfile, "detmp.XXX"); mktemp (tempfile); - outfilefd = creat (tempfile, S_IREAD | S_IWRITE); + outfilefd = emacs_open (tempfile, O_WRONLY | O_CREAT | O_TRUNC, + S_IREAD | S_IWRITE); if (outfilefd < 0) { emacs_close (filefd); report_file_error ("Opening process output file", @@ -535,15 +538,9 @@ if (NILP (error_file)) fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0); else if (STRINGP (error_file)) - { -#ifdef DOS_NT - fd_error = emacs_open (SSDATA (error_file), - O_WRONLY | O_TRUNC | O_CREAT | O_TEXT, - S_IREAD | S_IWRITE); -#else /* not DOS_NT */ - fd_error = creat (SSDATA (error_file), 0666); -#endif /* not DOS_NT */ - } + fd_error = emacs_open (SSDATA (error_file), + O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, + default_output_mode); if (fd_error < 0) { === modified file 'src/cygw32.c' --- src/cygw32.c 2013-01-02 16:13:04 +0000 +++ src/cygw32.c 2013-07-06 02:40:50 +0000 @@ -35,7 +35,7 @@ chdir_to_default_directory () { Lisp_Object new_cwd; - int old_cwd_fd = open (".", O_RDONLY | O_DIRECTORY); + int old_cwd_fd = emacs_open (".", O_RDONLY | O_DIRECTORY, 0); if (old_cwd_fd == -1) error ("could not open current directory: %s", strerror (errno)); === modified file 'src/dispnew.c' --- src/dispnew.c 2013-04-02 01:54:56 +0000 +++ src/dispnew.c 2013-07-06 02:40:50 +0000 @@ -22,7 +22,7 @@ #define DISPEXTERN_INLINE EXTERN_INLINE -#include +#include "sysstdio.h" #include #include "lisp.h" @@ -5605,17 +5605,17 @@ tty = CURTTY (); if (tty->termscript != 0) - { - block_input (); - fclose (tty->termscript); - unblock_input (); - } - tty->termscript = 0; + { + block_input (); + fclose (tty->termscript); + tty->termscript = 0; + unblock_input (); + } if (! NILP (file)) { file = Fexpand_file_name (file, Qnil); - tty->termscript = fopen (SSDATA (file), "w"); + tty->termscript = emacs_fopen (SSDATA (file), "w"); if (tty->termscript == 0) report_file_error ("Opening termscript", Fcons (file, Qnil)); } === modified file 'src/emacs.c' --- src/emacs.c 2013-07-04 06:20:55 +0000 +++ src/emacs.c 2013-07-06 02:40:50 +0000 @@ -2236,7 +2236,7 @@ error ("This function can only be called after loading the init files"); /* Get rid of stdin, stdout and stderr. */ - nfd = open ("/dev/null", O_RDWR); + nfd = emacs_open ("/dev/null", O_RDWR, 0); err |= nfd < 0; err |= dup2 (nfd, 0) < 0; err |= dup2 (nfd, 1) < 0; === modified file 'src/fileio.c' --- src/fileio.c 2013-07-05 16:58:01 +0000 +++ src/fileio.c 2013-07-06 02:40:50 +0000 @@ -20,7 +20,7 @@ #include #include #include -#include +#include "sysstdio.h" #include #include #include @@ -5618,7 +5618,7 @@ UNGCPRO; } - stream = fopen (SSDATA (listfile), "w"); + stream = emacs_fopen (SSDATA (listfile), "w"); } record_unwind_protect (do_auto_save_unwind, === modified file 'src/image.c' --- src/image.c 2013-07-04 15:25:54 +0000 +++ src/image.c 2013-07-06 02:40:50 +0000 @@ -18,7 +18,7 @@ along with GNU Emacs. If not, see . */ #include -#include +#include "sysstdio.h" #include #ifdef HAVE_PNG @@ -2274,7 +2274,7 @@ static unsigned char * slurp_file (char *file, ptrdiff_t *size) { - FILE *fp = fopen (file, "rb"); + FILE *fp = emacs_fopen (file, "rb"); unsigned char *buf = NULL; struct stat st; @@ -5723,7 +5723,7 @@ } /* Open the image file. */ - fp = fopen (SSDATA (file), "rb"); + fp = emacs_fopen (SSDATA (file), "rb"); if (!fp) { image_error ("Cannot open image file `%s'", file, Qnil); @@ -6484,7 +6484,7 @@ return 0; } - fp = fopen (SSDATA (file), "rb"); + fp = emacs_fopen (SSDATA (file), "rb"); if (fp == NULL) { image_error ("Cannot open `%s'", file, Qnil); === modified file 'src/keyboard.c' --- src/keyboard.c 2013-07-06 00:10:54 +0000 +++ src/keyboard.c 2013-07-06 02:40:50 +0000 @@ -23,7 +23,7 @@ #define BLOCKINPUT_INLINE EXTERN_INLINE #define KEYBOARD_INLINE EXTERN_INLINE -#include +#include "sysstdio.h" #include "lisp.h" #include "termchar.h" @@ -10129,7 +10129,7 @@ if (!NILP (file)) { file = Fexpand_file_name (file, Qnil); - dribble = fopen (SSDATA (file), "w"); + dribble = emacs_fopen (SSDATA (file), "w"); if (dribble == 0) report_file_error ("Opening dribble", Fcons (file, Qnil)); } === modified file 'src/lread.c' --- src/lread.c 2013-07-05 16:58:01 +0000 +++ src/lread.c 2013-07-06 02:40:50 +0000 @@ -20,7 +20,7 @@ #include -#include +#include "sysstdio.h" #include #include #include @@ -1297,7 +1297,7 @@ if (fd >= 0) { emacs_close (fd); - stream = fopen (SSDATA (efound), fmode); + stream = emacs_fopen (SSDATA (efound), fmode); } else stream = NULL; === modified file 'src/print.c' --- src/print.c 2013-07-02 03:41:16 +0000 +++ src/print.c 2013-07-06 02:40:50 +0000 @@ -20,7 +20,7 @@ #include -#include +#include "sysstdio.h" #include "lisp.h" #include "character.h" @@ -765,7 +765,7 @@ { file = Fexpand_file_name (file, Qnil); initial_stderr_stream = stderr; - stderr = fopen (SSDATA (file), NILP (append) ? "w" : "a"); + stderr = emacs_fopen (SSDATA (file), NILP (append) ? "w" : "a"); if (stderr == NULL) { stderr = initial_stderr_stream; === modified file 'src/sysdep.c' --- src/sysdep.c 2013-07-02 22:14:42 +0000 +++ src/sysdep.c 2013-07-06 02:40:50 +0000 @@ -22,7 +22,7 @@ #define SYSTIME_INLINE EXTERN_INLINE #include -#include +#include "sysstdio.h" #ifdef HAVE_PWD_H #include #include @@ -2151,15 +2151,29 @@ } #endif +/* Open FILE for Emacs use, using open flags OFLAG and mode MODE. + Do not fail merely because the open was interrupted by a signal. + Allow the user to quit. */ + int -emacs_open (const char *path, int oflag, int mode) -{ - register int rtnval; - - while ((rtnval = open (path, oflag, mode)) == -1 - && (errno == EINTR)) - QUIT; - return (rtnval); +emacs_open (const char *file, int oflags, int mode) +{ + int fd; + while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) + QUIT; + return fd; +} + +/* Open FILE as a stream for Emacs use, with mode MODE. + Act like emacs_open with respect to threads, signals, and quits. */ + +FILE * +emacs_fopen (char const *file, char const *mode) +{ + FILE *fp; + while (! (fp = fopen (file, mode)) && errno == EINTR) + QUIT; + return fp; } int @@ -2637,7 +2651,7 @@ EMACS_TIME up = make_emacs_time (0, 0); block_input (); - fup = fopen ("/proc/uptime", "r"); + fup = emacs_fopen ("/proc/uptime", "r"); if (fup) { @@ -2682,7 +2696,7 @@ char name[PATH_MAX]; block_input (); - fdev = fopen ("/proc/tty/drivers", "r"); + fdev = emacs_fopen ("/proc/tty/drivers", "r"); if (fdev) { @@ -2724,7 +2738,7 @@ unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ block_input (); - fmem = fopen ("/proc/meminfo", "r"); + fmem = emacs_fopen ("/proc/meminfo", "r"); if (fmem) { === added file 'src/sysstdio.h' --- src/sysstdio.h 1970-01-01 00:00:00 +0000 +++ src/sysstdio.h 2013-07-06 02:40:50 +0000 @@ -0,0 +1,2 @@ +#include +extern FILE *emacs_fopen (char const *, char const *); === modified file 'src/term.c' --- src/term.c 2013-06-03 19:28:13 +0000 +++ src/term.c 2013-07-06 02:40:50 +0000 @@ -2479,7 +2479,7 @@ const char *name; int fd; name = (const char *) ttyname (0); - fd = open (name, O_WRONLY); + fd = emacs_open (name, O_WRONLY, 0); SOME_FUNCTION (x, y, fd); close (fd); last_mouse_x = x; === modified file 'src/termcap.c' --- src/termcap.c 2013-02-02 17:14:24 +0000 +++ src/termcap.c 2013-07-06 02:40:50 +0000 @@ -427,11 +427,7 @@ /* Here we know we must search a file and termcap_name has its name. */ -#ifdef MSDOS - fd = open (termcap_name, O_RDONLY|O_TEXT, 0); -#else - fd = open (termcap_name, O_RDONLY, 0); -#endif + fd = emacs_open (termcap_name, O_RDONLY | O_TEXT, 0); if (fd < 0) return -1; === modified file 'src/unexaix.c' --- src/unexaix.c 2013-02-25 05:55:37 +0000 +++ src/unexaix.c 2013-07-06 02:40:50 +0000 @@ -42,6 +42,7 @@ #include #include "unexec.h" +#include "lisp.h" #define PERROR(file) report_error (file, new) #include @@ -132,11 +133,11 @@ { int new = -1, a_out = -1; - if (a_name && (a_out = open (a_name, O_RDONLY)) < 0) + if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0) { PERROR (a_name); } - if ((new = creat (new_name, 0666)) < 0) + if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { PERROR (new_name); } @@ -503,7 +504,7 @@ if (!lnnoptr || !f_hdr.f_symptr) return 0; - if ((new = open (new_name, O_RDWR)) < 0) + if ((new = emacs_open (new_name, O_RDWR, 0)) < 0) { PERROR (new_name); return -1; === modified file 'src/unexcoff.c' --- src/unexcoff.c 2013-02-25 05:55:37 +0000 +++ src/unexcoff.c 2013-07-06 02:40:50 +0000 @@ -52,6 +52,7 @@ #include #include "unexec.h" +#include "lisp.h" #define PERROR(file) report_error (file, new) @@ -486,7 +487,7 @@ #ifdef MSDOS if ((new = writedesc) < 0) #else - if ((new = open (new_name, O_RDWR)) < 0) + if ((new = emacs_open (new_name, O_RDWR, 0)) < 0) #endif { PERROR (new_name); @@ -525,11 +526,11 @@ { int new = -1, a_out = -1; - if (a_name && (a_out = open (a_name, O_RDONLY)) < 0) + if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0) { PERROR (a_name); } - if ((new = creat (new_name, 0666)) < 0) + if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { PERROR (new_name); } === modified file 'src/unexcw.c' --- src/unexcw.c 2013-03-22 16:52:31 +0000 +++ src/unexcw.c 2013-07-06 02:40:50 +0000 @@ -20,8 +20,8 @@ #include #include "unexec.h" +#include "lisp.h" -#include #include #include #include @@ -298,9 +298,9 @@ infile = add_exe_suffix_if_necessary (infile, infile_buffer); outfile = add_exe_suffix_if_necessary (outfile, outfile_buffer); - fd_in = open (infile, O_RDONLY | O_BINARY); + fd_in = emacs_open (infile, O_RDONLY | O_BINARY, 0); assert (fd_in >= 0); - fd_out = open (outfile, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0755); + fd_out = emacs_open (outfile, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0755); assert (fd_out >= 0); for (;;) { === modified file 'src/unexelf.c' --- src/unexelf.c 2013-05-07 20:55:47 +0000 +++ src/unexelf.c 2013-07-06 02:40:50 +0000 @@ -386,9 +386,8 @@ Instead we read the whole file, modify it, and write it out. */ #include -#include - -extern _Noreturn void fatal (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); +#include "unexec.h" +#include "lisp.h" #include #include @@ -672,7 +671,7 @@ /* Open the old file, allocate a buffer of the right size, and read in the file contents. */ - old_file = open (old_name, O_RDONLY); + old_file = emacs_open (old_name, O_RDONLY, 0); if (old_file < 0) fatal ("Can't open %s for reading: %s", old_name, strerror (errno)); @@ -681,7 +680,7 @@ fatal ("Can't fstat (%s): %s", old_name, strerror (errno)); #if MAP_ANON == 0 - mmap_fd = open ("/dev/zero", O_RDONLY); + mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0); if (mmap_fd < 0) fatal ("Can't open /dev/zero for reading: %s", strerror (errno)); #endif @@ -801,7 +800,7 @@ the image of the new file. Set pointers to various interesting objects. */ - new_file = open (new_name, O_RDWR | O_CREAT, 0666); + new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0666); if (new_file < 0) fatal ("Can't creat (%s): %s", new_name, strerror (errno)); === modified file 'src/unexhp9k800.c' --- src/unexhp9k800.c 2011-07-10 08:20:10 +0000 +++ src/unexhp9k800.c 2013-07-06 02:40:50 +0000 @@ -51,6 +51,7 @@ #include #include "unexec.h" +#include "lisp.h" #include #include @@ -268,10 +269,10 @@ intact. NOT implemented. */ /* Open the input and output a.out files */ - old = open (old_name, O_RDONLY); + old = emacs_open (old_name, O_RDONLY, 0); if (old < 0) { perror (old_name); exit (1); } - new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777); + new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777); if (new < 0) { perror (new_name); exit (1); } === modified file 'src/unexmacosx.c' --- src/unexmacosx.c 2013-01-23 01:51:49 +0000 +++ src/unexmacosx.c 2013-07-06 02:40:50 +0000 @@ -97,6 +97,7 @@ #undef free #include "unexec.h" +#include "lisp.h" #include #include @@ -1322,13 +1323,13 @@ unexec_error ("Unexec from a dumped executable is not supported."); pagesize = getpagesize (); - infd = open (infile, O_RDONLY, 0); + infd = emacs_open (infile, O_RDONLY, 0); if (infd < 0) { unexec_error ("cannot open input file `%s'", infile); } - outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755); + outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755); if (outfd < 0) { close (infd); === modified file 'src/w32term.c' --- src/w32term.c 2013-07-04 10:25:54 +0000 +++ src/w32term.c 2013-07-06 02:40:50 +0000 @@ -6621,7 +6621,7 @@ } #ifdef CYGWIN - if ((w32_message_fd = open ("/dev/windows", O_RDWR | O_CLOEXEC)) == -1) + if ((w32_message_fd = emacs_open ("/dev/windows", O_RDWR, 0)) == -1) fatal ("opening /dev/windows: %s", strerror (errno)); #endif /* CYGWIN */ === modified file 'src/xfaces.c' --- src/xfaces.c 2013-07-05 16:58:01 +0000 +++ src/xfaces.c 2013-07-06 02:40:50 +0000 @@ -200,7 +200,7 @@ used to fill in unspecified attributes of the default face. */ #include -#include +#include "sysstdio.h" #include #include @@ -6290,7 +6290,7 @@ CHECK_STRING (filename); abspath = Fexpand_file_name (filename, Qnil); - fp = fopen (SSDATA (abspath), "rt"); + fp = emacs_fopen (SSDATA (abspath), "rt"); if (fp) { char buf[512]; ------------------------------------------------------------ revno: 113295 committer: Glenn Morris branch nick: trunk timestamp: Fri 2013-07-05 19:32:13 -0700 message: * admin/admin.el (make-manuals): Avoid hard-coding list of misc manuals. (manual-misc-manuals): New function. diff: === modified file 'admin/ChangeLog' --- admin/ChangeLog 2013-07-05 16:10:47 +0000 +++ admin/ChangeLog 2013-07-06 02:32:13 +0000 @@ -1,3 +1,8 @@ +2013-07-06 Glenn Morris + + * admin.el (manual-misc-manuals): New function. + (make-manuals): Avoid hard-coding list of misc manuals. + 2013-07-05 Glenn Morris * admin.el (make-manuals): Use a standard location for lispintro. === modified file 'admin/admin.el' --- admin/admin.el 2013-07-05 16:10:47 +0000 +++ admin/admin.el 2013-07-06 02:32:13 +0000 @@ -193,6 +193,22 @@ ;;; Various bits of magic for generating the web manuals +(defun manual-misc-manuals (root) + "Return doc/misc manuals as list of strings." + ;; Like `make -C doc/misc echo-info', but works if unconfigured. + (with-temp-buffer + (insert-file-contents (expand-file-name "doc/misc/Makefile.in" root)) + (search-forward "INFO_TARGETS = ") + (let ((start (point)) + res) + (end-of-line) + (while (and (looking-back "\\\\") + (zerop (forward-line 1))) + (end-of-line)) + (split-string (replace-regexp-in-string + "\\(\\\\\\|\\.info\\)" "" + (buffer-substring start (point))))))) + (defun make-manuals (root) "Generate the web manuals for the Emacs webpage." (interactive "DEmacs root directory: ") @@ -229,18 +245,8 @@ (manual-pdf texi (expand-file-name "eintr.pdf" pdf-dir)) (manual-ps texi (expand-file-name "eintr.ps" ps-dir))) ;; Misc manuals - (let ((manuals '("ada-mode" "auth" "autotype" "bovine" "calc" "cc-mode" - "cl" "dbus" "dired-x" "ebrowse" "ede" "ediff" - "edt" "eieio" "emacs-gnutls" "emacs-mime" "epa" "erc" "ert" - "eshell" "eudc" "faq" "flymake" "forms" - "gnus" "htmlfontify" "idlwave" "info" - "mairix-el" "message" "mh-e" "newsticker" - "nxml-mode" "org" "pcl-cvs" "pgg" "rcirc" - "reftex" "remember" "sasl" "sc" "semantic" - "ses" "sieve" "smtpmail" "speedbar" "srecode" "tramp" - "url" "vip" "viper" "widget" "wisent" "woman"))) - (dolist (manual manuals) - (manual-misc-html manual root html-node-dir html-mono-dir))) + (dolist (manual (manual-misc-manuals root)) + (manual-misc-html manual root html-node-dir html-mono-dir)) (message "Manuals created in %s" dest))) (defconst manual-doctype-string ------------------------------------------------------------ revno: 113294 [merge] committer: Glenn Morris branch nick: trunk timestamp: Fri 2013-07-05 18:39:21 -0700 message: Merge from emacs-24; up to r111382 diff: === modified file 'doc/lispintro/ChangeLog' --- doc/lispintro/ChangeLog 2013-07-03 03:20:04 +0000 +++ doc/lispintro/ChangeLog 2013-07-06 01:39:21 +0000 @@ -1,3 +1,8 @@ +2013-07-06 Glenn Morris + + * emacs-lisp-intro.texi (Top): + Move WWW_GNU_ORG section outside @copying, update URL. + 2013-07-03 Glenn Morris * emacs-lisp-intro.texi (edebug): Fix cross-references. === modified file 'doc/lispintro/emacs-lisp-intro.texi' --- doc/lispintro/emacs-lisp-intro.texi 2013-07-03 03:20:04 +0000 +++ doc/lispintro/emacs-lisp-intro.texi 2013-07-06 01:39:21 +0000 @@ -112,14 +112,6 @@ @ifnottex Distributed with Emacs version @value{EMACSVER}. @end ifnottex -@ifset WWW_GNU_ORG -@html -

The homepage for GNU Emacs is at -http://www.gnu.org/software/emacs/. -
To view this manual in other formats, click -here. -@end html -@end ifset @sp 1 Copyright @copyright{} 1990--1995, 1997, 2001--2013 Free Software Foundation, Inc. @@ -211,6 +203,15 @@ @node Top @top An Introduction to Programming in Emacs Lisp +@ifset WWW_GNU_ORG +@html +

The homepage for GNU Emacs is at +http://www.gnu.org/software/emacs/.
+To view this manual in other formats, click +here. +@end html +@end ifset + @insertcopying This master menu first lists each chapter and index; then it lists === modified file 'doc/lispref/ChangeLog' --- doc/lispref/ChangeLog 2013-07-03 03:20:04 +0000 +++ doc/lispref/ChangeLog 2013-07-06 01:39:21 +0000 @@ -1,3 +1,7 @@ +2013-07-06 Glenn Morris + + * elisp.texi (Top): Move WWW_GNU_ORG section outside @copying. + 2013-07-03 Glenn Morris * debugging.texi (Debugging): === modified file 'doc/lispref/elisp.texi' --- doc/lispref/elisp.texi 2013-03-16 22:08:22 +0000 +++ doc/lispref/elisp.texi 2013-07-06 01:39:21 +0000 @@ -97,16 +97,6 @@ This is the @cite{GNU Emacs Lisp Reference Manual} @end ifnottex corresponding to Emacs version @value{EMACSVER}. -@ifset WWW_GNU_ORG -@html -

The homepage for GNU Emacs is at -http://www.gnu.org/software/emacs/.
-For information on using Emacs, refer to -the Emacs -Manual.
To view this manual in other formats, -click here. -@end html -@end ifset Copyright @copyright{} 1990--1996, 1998--2013 Free Software Foundation, Inc. @@ -167,6 +157,17 @@ @node Top @top Emacs Lisp +@ifset WWW_GNU_ORG +@html +

The homepage for GNU Emacs is at +http://www.gnu.org/software/emacs/.
+For information on using Emacs, refer to the +Emacs Manual.
+To view this manual in other formats, click +here. +@end html +@end ifset + @insertcopying @end ifnottex === modified file 'doc/misc/ChangeLog' --- doc/misc/ChangeLog 2013-07-03 21:07:48 +0000 +++ doc/misc/ChangeLog 2013-07-06 01:39:21 +0000 @@ -1,3 +1,30 @@ +2013-07-06 Glenn Morris + + * mh-e.texi: Fix external links. + (Using This Manual): Printed elisp manuals no longer available. + + * newsticker.texi (Overview): Update URL. + + * nxml-mode.texi (Introduction): Update URL. + + * org.texi (JavaScript support): Fix URL. + + * wisent.texi (Wisent Overview): Remove incorrect, unnecessary uref. + + * eudc.texi (CCSO PH/QI): Remove defunct URL. + + * dbus.texi (Introspection): Update URL to a less defunct one. + + * gnus.texi (Top): Restrict "Other related manuals" to info output. + (Foreign Groups): Use @indicateurl for examples. + (Direct Functions): Remove defunct URL. + (RSS): Update URL. + + * gnus-faq.texi (FAQ 5-8, FAQ 6-3): Remove defunct URLs. + (FAQ 7-1): Update URL. + + * pgg.texi (Top, Overview): Add note about obsolescence. + 2013-07-03 Paul Eggert * texinfo.tex: Merge from gnulib. === modified file 'doc/misc/dbus.texi' --- doc/misc/dbus.texi 2013-01-01 09:11:05 +0000 +++ doc/misc/dbus.texi 2013-07-03 07:51:34 +0000 @@ -403,8 +403,11 @@ The interface offers also a signal, which returns 2 parameters: an integer, and an array consisting of elements which are a struct of a string and 2 boolean values.@footnote{ The interfaces of the service -@samp{org.freedesktop.Hal} are described at -@uref{http://people.freedesktop.org/~david/hal-spec/hal-spec.html#interfaces}.} +@samp{org.freedesktop.Hal} are described in +@c Previous link is gone. Since HAL is now obsolete, this URL +@c (unchanged in ~ 4 years) feels like it might go too... +@uref{http://people.freedesktop.org/~dkukawka/hal-spec-git/hal-spec.html#interfaces, +the HAL specification}.} @end defun @defun dbus-introspect-xml bus service path === modified file 'doc/misc/eudc.texi' --- doc/misc/eudc.texi 2013-06-24 06:58:52 +0000 +++ doc/misc/eudc.texi 2013-07-06 01:39:21 +0000 @@ -150,14 +150,17 @@ configured to. Nowadays this system is not widely used. The system consists of two parts: a database server traditionally called -@samp{qi} and a command-line client called @samp{ph}. As of 2010, the -code can still be downloaded from @url{http://www-dev.cites.uiuc.edu/ph/}. +@samp{qi} and a command-line client called @samp{ph}. +@ignore +Until 2010, the code could be downloaded from +@url{http://www-dev.cites.uiuc.edu/ph/}. +@end ignore -The original command-line @samp{ph} client that comes with the -@samp{ph/qi} distribution provides additional features like the -possibility to communicate with the server in login-mode which makes it -possible to change records in the database. This is not implemented in -EUDC. +The original command-line @samp{ph} client that came with the +@samp{ph/qi} distribution provided additional features that are +not implemented in EUDC, like the possibility to communicate with the +server in login-mode, which made it possible to change records in the +database. @node BBDB === modified file 'doc/misc/gnus-faq.texi' --- doc/misc/gnus-faq.texi 2013-03-07 10:24:23 +0000 +++ doc/misc/gnus-faq.texi 2013-07-06 01:39:21 +0000 @@ -1518,8 +1518,9 @@ If you can't use compface, there's an online X-face converter at @uref{http://www.dairiki.org/xface/}. -If you use MS Windows, you could also use the WinFace program from -@uref{http://www.xs4all.nl/~walterln/winface/}. +If you use MS Windows, you could also use the WinFace program, +which used to be available from +@indicateurl{http://www.xs4all.nl/~walterln/winface/}. Now you only have to tell Gnus to include the X-face in your postings by saying @example @@ -1812,15 +1813,20 @@ Of course you can also use grep to search through your local mail, but this is both slow for big archives and inconvenient since you are not displaying the found mail -in Gnus. Here comes nnir into action. Nnir is a front end +in Gnus. Here nnir comes into action. Nnir is a front end to search engines like swish-e or swish++ and -others. You index your mail with one of those search +others. You index your mail with one of those search engines and with the help of nnir you can search through the indexed mail and generate a temporary group with all -messages which met your search criteria. If this sound -cool to you get nnir.el from +messages which met your search criteria. If this sounds +cool to you, get nnir.el from +@c FIXME Isn't this file in Gnus? +@ignore +@c Dead link 2013/7. @uref{ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/} -or @uref{ftp://ftp.is.informatik.uni-duisburg.de/pub/src/emacs/}. +or +@end ignore +@uref{ftp://ftp.is.informatik.uni-duisburg.de/pub/src/emacs/}. Instructions on how to use it are at the top of the file. @node FAQ 6-4 @@ -1943,7 +1949,7 @@ @uref{http://infa.abo.fi/~patrik/sn/, sn}, of course you can also install a full featured news server like -@uref{http://www.isc.org/products/INN/, inn}. +@uref{http://www.isc.org/software/inn/, inn}. Then you want to fetch your Mail, popular choices are @uref{http://www.catb.org/~esr/fetchmail/, fetchmail} and @uref{http://pyropus.ca/software/getmail/, getmail}. === modified file 'doc/misc/gnus.texi' --- doc/misc/gnus.texi 2013-07-02 10:38:58 +0000 +++ doc/misc/gnus.texi 2013-07-06 01:39:21 +0000 @@ -420,6 +420,9 @@ * Index:: Variable, function and concept index. * Key Index:: Key Index. +@c Doesn't work right in html. +@c FIXME Do this in a more standard way. +@ifinfo Other related manuals * Message:(message). Composing messages. @@ -427,6 +430,7 @@ * Sieve:(sieve). Managing Sieve scripts in Emacs. * EasyPG:(epa). @acronym{PGP/MIME} with Gnus. * SASL:(sasl). @acronym{SASL} authentication in Emacs. +@end ifinfo @detailmenu --- The Detailed Node Listing --- @@ -2712,11 +2716,11 @@ This command is similar to @code{gnus-read-ephemeral-gmane-group}, but the group name and the article number and range are constructed from a given @acronym{URL}. Supported @acronym{URL} formats include: -@url{http://thread.gmane.org/gmane.foo.bar/12300/focus=12399}, -@url{http://thread.gmane.org/gmane.foo.bar/12345/}, -@url{http://article.gmane.org/gmane.foo.bar/12345/}, -@url{http://permalink.gmane.org/gmane.foo.bar/12345/}, and -@url{http://news.gmane.org/group/gmane.foo.bar/thread=12345}. +@indicateurl{http://thread.gmane.org/gmane.foo.bar/12300/focus=12399}, +@indicateurl{http://thread.gmane.org/gmane.foo.bar/12345/}, +@indicateurl{http://article.gmane.org/gmane.foo.bar/12345/}, +@indicateurl{http://permalink.gmane.org/gmane.foo.bar/12345/}, and +@indicateurl{http://news.gmane.org/group/gmane.foo.bar/thread=12345}. @item gnus-read-ephemeral-emacs-bug-group @findex gnus-read-ephemeral-emacs-bug-group @@ -13809,9 +13813,12 @@ @findex nntp-open-ssl-stream @item nntp-open-ssl-stream Opens a connection to a server over a @dfn{secure} channel. To use -this you must have @uref{http://www.openssl.org, OpenSSL} or -@uref{ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL, SSLeay} installed. You -then define a server as follows: +this you must have @uref{http://www.openssl.org, OpenSSL} +@ignore +@c Defunct URL, ancient package, so don't mention it. +or @uref{ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL, SSLeay} +@end ignore +installed. You then define a server as follows: @lisp ;; @r{"snews" is port 563 and is predefined in our @file{/etc/services}} @@ -16953,7 +16960,7 @@ @acronym{RSS} is a format for summarizing headlines from news related sites (such as BBC or CNN). But basically anything list-like can be presented as an @acronym{RSS} feed: weblogs, changelogs or recent -changes to a wiki (e.g., @url{http://cliki.net/recent-changes.rdf}). +changes to a wiki (e.g., @url{http://cliki.net/site/recent-changes}). @acronym{RSS} has a quite regular and nice interface, and it's possible to get the information Gnus needs to keep groups updated. === modified file 'doc/misc/mh-e.texi' --- doc/misc/mh-e.texi 2013-07-03 03:20:04 +0000 +++ doc/misc/mh-e.texi 2013-07-06 01:39:21 +0000 @@ -1121,38 +1121,23 @@ @footnote{The @cite{GNU Emacs Lisp Reference Manual} may be available online in the Info system by typing @kbd{C-h i m Emacs Lisp @key{RET}}. It is also available online at @* -@uref{http://www.gnu.org/savannah-checkouts/gnu/emacs/manual/html_node/elisp/}. -You can also order a printed manual, which has the desirable -side-effect of helping to support the Free Software Foundation which -made all this great software available. You can find an order form by -running @kbd{C-h C-d}, or you can request an order form from @i{gnu at -gnu.org}.} +@uref{http://www.gnu.org/software/emacs/manual/elisp.html}.} @end iftex @ifinfo @footnote{@xref{Top, The GNU Emacs Lisp Reference Manual, , elisp, GNU Emacs Lisp Reference Manual}, which may be available online in the Info system. It is also available online at -@uref{http://www.gnu.org/savannah-checkouts/gnu/emacs/manual/html_node/elisp/}. -You can also order a printed manual, which has the desirable -side-effect of helping to support the Free Software Foundation which -made all this great software available. You can find an order form by -running @kbd{C-h C-d}, or you can request an order form from @i{gnu at -gnu.org}.} +@uref{http://www.gnu.org/software/emacs/manual/elisp.html}.} @end ifinfo @ifhtml @footnote{The -@uref{http://www.gnu.org/savannah-checkouts/gnu/emacs/manual/html_node/elisp/, +@uref{http://www.gnu.org/software/emacs/manual/elisp.html, The GNU Emacs Lisp Reference Manual} may also be available online in -the Info system by typing @kbd{C-h i m Emacs Lisp @key{RET}}. You can -also order a printed manual, which has the desirable side-effect of -helping to support the Free Software Foundation which made all this -great software available. You can find an order form by running -@kbd{C-h C-d}, or you can request an order form from @i{gnu at -gnu.org}.} +the Info system by typing @kbd{C-h i m Emacs Lisp @key{RET}}.} @end ifhtml and you can look at the code itself for examples. Look in the Emacs Lisp directory on your system (such as -@file{/usr/local/lib/emacs/lisp/mh-e}) and find all the @file{mh-*.el} +@file{/usr/local/share/emacs/lisp/mh-e}) and find all the @file{mh-*.el} files there. When calling MH-E and other Emacs Lisp functions directly from Emacs Lisp code, you'll need to know the correct arguments. Use the online help for this. For example, try @kbd{C-h f @@ -2848,7 +2833,7 @@ @end ifinfo @ifhtml See -@uref{http://www.dk.xemacs.org/Documentation/packages/html/pgg.html, +@uref{http://www.gnu.org/software/emacs/manual/pgg.html, @cite{The PGG Manual}}. @end ifhtml @@ -5058,7 +5043,7 @@ @vindex mh-yank-behavior For example, if you use the hook function -@uref{http://shasta.cs.uiuc.edu/~lrclause/tc.html, +@uref{http://www.emacswiki.org/emacs/TrivialCite, @code{trivial-cite}} (which is NOT part of Emacs), set @code{mh-yank-behavior} to @samp{Body and Header}. @@ -5615,7 +5600,7 @@ @end ifinfo @ifhtml See -@uref{http://www.dk.xemacs.org/Documentation/packages/html/pgg.html, +@uref{http://www.gnu.org/software/emacs/manual/pgg.html, @cite{The PGG Manual}}. @end ifhtml === modified file 'doc/misc/newsticker.texi' --- doc/misc/newsticker.texi 2013-01-01 09:11:05 +0000 +++ doc/misc/newsticker.texi 2013-07-04 01:55:25 +0000 @@ -89,7 +89,7 @@ as well as the following Atom formats: @item Atom 0.3 @item Atom 1.0 (see -@uref{http://www.ietf.org/internet-drafts/draft-ietf-atompub-format-11.txt}). +@uref{https://datatracker.ietf.org/doc/rfc4287/}). @end itemize That makes Newsticker.el an ``Atom aggregator'', ``RSS reader'', ``Feed === modified file 'doc/misc/nxml-mode.texi' --- doc/misc/nxml-mode.texi 2013-01-01 09:11:05 +0000 +++ doc/misc/nxml-mode.texi 2013-07-04 01:53:56 +0000 @@ -86,7 +86,11 @@ @noindent To convert a RELAX NG XML syntax (@samp{.rng}) schema to a RNC one, you can also use the XSLT stylesheet from +@url{https://github.com/oleg-pavliv/emacs/tree/master/xsl}. +@ignore +@c Original location, now defunct. @url{http://www.pantor.com/download.html}. +@end ignore To convert a W3C XML Schema to an RNC schema, you need first to convert it to RELAX NG XML syntax using the RELAX NG converter tool @code{rngconv} === modified file 'doc/misc/org.texi' --- doc/misc/org.texi 2013-02-28 06:30:48 +0000 +++ doc/misc/org.texi 2013-07-06 01:39:21 +0000 @@ -10393,7 +10393,7 @@ script is available at @url{http://orgmode.org/org-info.js} and you can find the documentation for it at @url{http://orgmode.org/worg/code/org-info-js/}. We host the script at our site, but if you use it a lot, you might -not want to be dependent on @url{orgmode.org} and prefer to install a local +not want to be dependent on @url{http://orgmode.org} and prefer to install a local copy on your own web server. To use the script, you need to make sure that the @file{org-jsinfo.el} module === modified file 'doc/misc/pgg.texi' --- doc/misc/pgg.texi 2013-01-06 10:34:26 +0000 +++ doc/misc/pgg.texi 2013-07-03 06:42:43 +0000 @@ -54,6 +54,8 @@ PGG is an interface library between Emacs and various tools for secure communication. PGG also provides a simple user interface to encrypt, decrypt, sign, and verify MIME messages. +This package is obsolete; for new code we recommend EasyPG instead. +@xref{Top,, EasyPG, epa, EasyPG Assistant User's Manual}. @ifnottex @insertcopying @@ -78,6 +80,9 @@ deal with detached PGP messages, normally used in PGP/MIME infrastructure. This was the main reason why I wrote the new library. +Note that the PGG library is now obsolete, replaced by EasyPG. +@xref{Top,, EasyPG, epa, EasyPG Assistant User's Manual}. + PGP/MIME is an application of MIME Object Security Services (RFC1848). The standard is documented in RFC2015. === modified file 'doc/misc/wisent.texi' --- doc/misc/wisent.texi 2013-01-03 02:37:57 +0000 +++ doc/misc/wisent.texi 2013-07-06 01:39:21 +0000 @@ -113,9 +113,6 @@ For more details on the basic concepts for understanding Wisent, it is worthwhile to read the @ref{Top, Bison Manual, , bison}. -@ifhtml -@uref{http://www.gnu.org/manual/bison/html_node/index.html}. -@end ifhtml Wisent can generate compilers compatible with the @semantic{} tool set. See the @ref{Top, Semantic Manual, , semantic}. ------------------------------------------------------------ revno: 113293 fixes bug: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=14782 committer: Stefan Monnier branch nick: trunk timestamp: Fri 2013-07-05 20:10:54 -0400 message: * lisp/subr.el (read-quoted-char): Use read-key. (sit-for): Let read-event decode tty input. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-07-05 14:03:35 +0000 +++ lisp/ChangeLog 2013-07-06 00:10:54 +0000 @@ -1,8 +1,13 @@ +2013-07-06 Stefan Monnier + + * subr.el (read-quoted-char): Use read-key. + (sit-for): Let read-event decode tty input (bug#14782). + 2013-07-05 Stephen Berman * calendar/todo-mode.el: Add handling of file deletion, both by - mode command and externally. Fix various related bugs. Clarify - Commentary and improve some documentation strings and code. + mode command and externally. Fix various related bugs. + Clarify Commentary and improve some documentation strings and code. (todo-delete-file): New command. (todo-check-file): New function. (todo-show): Handle external deletion of the file we're trying to @@ -20,8 +25,8 @@ (todo-find-archive): Check whether there are any archives. Replace unnecessary setq by let-binding. (todo-archive-done-item): Use find-file-noselect to get the - archive buffer whether or not the archive already exists. Remove - superfluous code. Use file size instead of buffer-file-name to + archive buffer whether or not the archive already exists. + Remove superfluous code. Use file size instead of buffer-file-name to check if the archive is new; if it is, update list of archives. (todo-default-todo-file): Allow nil to be a valid value for when there are no todo files. @@ -38,9 +43,9 @@ 2013-07-05 Michael Albinus - * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support - both "gvfs-monitor-dir" and "inotifywait". - (tramp-sh-file-inotifywait-process-filter): Renamed from + * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): + Support both "gvfs-monitor-dir" and "inotifywait". + (tramp-sh-file-inotifywait-process-filter): Rename from `tramp-sh-file-notify-process-filter'. (tramp-sh-file-gvfs-monitor-dir-process-filter) (tramp-get-remote-gvfs-monitor-dir): New defuns. @@ -69,8 +74,8 @@ * subr.el (file-notify-handle-event): Move function to filenotify.el. - * net/tramp.el (tramp-file-name-for-operation): Handle - `file-notify-add-watch' and `file-notify-rm-watch'. + * net/tramp.el (tramp-file-name-for-operation): + Handle `file-notify-add-watch' and `file-notify-rm-watch'. * net/tramp-sh.el (tramp-sh-file-name-handler-alist): Add handler for `file-notify-add-watch' and `file-notify-rm-watch'. === modified file 'lisp/subr.el' --- lisp/subr.el 2013-07-04 09:39:36 +0000 +++ lisp/subr.el 2013-07-06 00:10:54 +0000 @@ -1990,20 +1990,14 @@ or the octal character code. RET terminates the character code and is discarded; any other non-digit terminates the character code and is then used as input.")) - (setq char (read-event (and prompt (format "%s-" prompt)) t)) + (setq translated (read-key (and prompt (format "%s-" prompt)))) (if inhibit-quit (setq quit-flag nil))) - ;; Translate TAB key into control-I ASCII character, and so on. - ;; Note: `read-char' does it using the `ascii-character' property. - ;; We should try and use read-key instead. - (let ((translation (lookup-key local-function-key-map (vector char)))) - (setq translated (if (arrayp translation) - (aref translation 0) - char))) (if (integerp translated) (setq translated (char-resolve-modifiers translated))) (cond ((null translated)) ((not (integerp translated)) - (setq unread-command-events (list char) + (setq unread-command-events + (listify-key-sequence (this-single-command-raw-keys)) done t)) ((/= (logand translated ?\M-\^@) 0) ;; Turn a meta-character into a character with the 0200 bit set. @@ -2022,7 +2016,8 @@ ((and (not first) (eq translated ?\C-m)) (setq done t)) ((not first) - (setq unread-command-events (list char) + (setq unread-command-events + (listify-key-sequence (this-single-command-raw-keys)) done t)) (t (setq code translated done t))) @@ -2186,6 +2181,7 @@ where the optional arg MILLISECONDS specifies an additional wait period, in milliseconds; this was useful when Emacs was built without floating point support." + (declare (advertised-calling-convention (seconds &optional nodisp) "22.1")) (if (numberp nodisp) (setq seconds (+ seconds (* 1e-3 nodisp)) nodisp obsolete) @@ -2200,7 +2196,10 @@ (or nodisp (redisplay))) (t (or nodisp (redisplay)) - (let ((read (read-event nil nil seconds))) + ;; FIXME: we should not read-event here at all, because it's much too + ;; difficult to reliably "undo" a read-event by pushing it onto + ;; unread-command-events. + (let ((read (read-event nil t seconds))) (or (null read) (progn ;; If last command was a prefix arg, e.g. C-u, push this event onto @@ -2210,7 +2209,6 @@ (setq read (cons t read))) (push read unread-command-events) nil)))))) -(set-advertised-calling-convention 'sit-for '(seconds &optional nodisp) "22.1") (defun y-or-n-p (prompt) "Ask user a \"y or n\" question. Return t if answer is \"y\". @@ -2451,11 +2449,12 @@ (recenter (/ (window-height) 2)))) (message (or message "Type %s to continue editing.") (single-key-description exit-char)) - (let ((event (read-event))) + (let ((event (read-key))) ;; `exit-char' can be an event, or an event description list. (or (eq event exit-char) (eq event (event-convert-list exit-char)) - (setq unread-command-events (list event))))) + (setq unread-command-events + (append (this-single-command-raw-keys)))))) (delete-overlay ol)))) === modified file 'src/keyboard.c' --- src/keyboard.c 2013-06-11 04:15:49 +0000 +++ src/keyboard.c 2013-07-06 00:10:54 +0000 @@ -2286,7 +2286,6 @@ XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL)); } - /* FIXME: Decode tty keyboard input here. */ return c; } ------------------------------------------------------------ revno: 113292 committer: Paul Eggert branch nick: trunk timestamp: Fri 2013-07-05 09:58:01 -0700 message: Remove duplicate #include directives. * alloc.c [GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES]: * xfaces.c: Don't include stdio.h twice. * buffer.c [USE_MMAP_FOR_BUFFERS]: Don't include sys/types.h or stdio.h twice. * fileio.c [WINDOWSNT | MSDOS]: Don't include fcntl.h twice. * lread.c: Don't include coding.h twice. * nsfont.m: Don't include frame.h twice. * process.c [HAVE_RES_INIT]: Don't include twice. * ralloc.c: Don't include twice. * xdisp.c: Don't include font.h twice. * xterm.c: Don't include fontset.h twice. * xterm.h [USE_X_TOOLKIT]: Don't include X11/StringDefs.h twice. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-07-04 15:25:54 +0000 +++ src/ChangeLog 2013-07-05 16:58:01 +0000 @@ -1,3 +1,20 @@ +2013-07-05 Paul Eggert + + Remove duplicate #include directives. + * alloc.c [GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES]: + * xfaces.c: + Don't include stdio.h twice. + * buffer.c [USE_MMAP_FOR_BUFFERS]: + Don't include sys/types.h or stdio.h twice. + * fileio.c [WINDOWSNT | MSDOS]: Don't include fcntl.h twice. + * lread.c: Don't include coding.h twice. + * nsfont.m: Don't include frame.h twice. + * process.c [HAVE_RES_INIT]: Don't include twice. + * ralloc.c: Don't include twice. + * xdisp.c: Don't include font.h twice. + * xterm.c: Don't include fontset.h twice. + * xterm.h [USE_X_TOOLKIT]: Don't include X11/StringDefs.h twice. + 2013-07-04 Paul Eggert Scale ImageMagick images more carefully. === modified file 'src/alloc.c' --- src/alloc.c 2013-07-02 03:41:16 +0000 +++ src/alloc.c 2013-07-05 16:58:01 +0000 @@ -247,10 +247,6 @@ #if GC_MARK_STACK || defined GC_MALLOC_CHECK -#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES -#include /* For fprintf. */ -#endif - /* A unique object in pure space used to make some Lisp objects on free lists recognizable in O(1). */ === modified file 'src/buffer.c' --- src/buffer.c 2013-06-30 22:29:23 +0000 +++ src/buffer.c 2013-07-05 16:58:01 +0000 @@ -4603,7 +4603,6 @@ #ifdef USE_MMAP_FOR_BUFFERS -#include #include #ifndef MAP_ANON @@ -4618,8 +4617,6 @@ #define MAP_FAILED ((void *) -1) #endif -#include - #if MAP_ANON == 0 #include #endif === modified file 'src/fileio.c' --- src/fileio.c 2013-07-04 09:29:28 +0000 +++ src/fileio.c 2013-07-05 16:58:01 +0000 @@ -55,7 +55,6 @@ #ifdef WINDOWSNT #define NOMINMAX 1 #include -#include #include #include "w32.h" #endif /* not WINDOWSNT */ @@ -63,7 +62,6 @@ #ifdef MSDOS #include "msdos.h" #include -#include #endif #ifdef DOS_NT === modified file 'src/lread.c' --- src/lread.c 2013-06-13 22:24:52 +0000 +++ src/lread.c 2013-07-05 16:58:01 +0000 @@ -38,7 +38,6 @@ #include "keyboard.h" #include "frame.h" #include "termhooks.h" -#include "coding.h" #include "blockinput.h" #ifdef MSDOS === modified file 'src/nsfont.m' --- src/nsfont.m 2013-06-17 21:10:31 +0000 +++ src/nsfont.m 2013-07-05 16:58:01 +0000 @@ -33,7 +33,6 @@ #include "window.h" #include "fontset.h" #include "nsterm.h" -#include "frame.h" #include "character.h" #include "font.h" #include "termchar.h" === modified file 'src/process.c' --- src/process.c 2013-07-02 12:46:43 +0000 +++ src/process.c 2013-07-05 16:58:01 +0000 @@ -78,7 +78,6 @@ #endif #ifdef HAVE_RES_INIT -#include #include #include #endif === modified file 'src/ralloc.c' --- src/ralloc.c 2013-02-22 19:23:12 +0000 +++ src/ralloc.c 2013-07-05 16:58:01 +0000 @@ -43,8 +43,6 @@ #else /* not emacs */ #include - -#include #include #endif /* not emacs */ === modified file 'src/xdisp.c' --- src/xdisp.c 2013-07-02 15:52:07 +0000 +++ src/xdisp.c 2013-07-05 16:58:01 +0000 @@ -313,8 +313,6 @@ #include "gtkutil.h" #endif -#include "font.h" - #ifndef FRAME_X_OUTPUT #define FRAME_X_OUTPUT(f) ((f)->output_data.x) #endif === modified file 'src/xfaces.c' --- src/xfaces.c 2013-04-07 04:41:19 +0000 +++ src/xfaces.c 2013-07-05 16:58:01 +0000 @@ -203,7 +203,6 @@ #include #include #include -#include /* This needs to be before termchar.h */ #include "lisp.h" #include "character.h" === modified file 'src/xterm.c' --- src/xterm.c 2013-06-30 15:24:14 +0000 +++ src/xterm.c 2013-07-05 16:58:01 +0000 @@ -69,7 +69,6 @@ #include "atimer.h" #include "keymap.h" #include "font.h" -#include "fontset.h" #include "xsettings.h" #include "xgselect.h" #include "sysselect.h" === modified file 'src/xterm.h' --- src/xterm.h 2013-05-09 14:49:56 +0000 +++ src/xterm.h 2013-07-05 16:58:01 +0000 @@ -38,8 +38,6 @@ #include /* foul, but we need this to use our own window inside a widget instead of one that Xt creates... */ -#include - typedef Widget xt_or_gtk_widget; #endif ------------------------------------------------------------ revno: 113291 committer: Glenn Morris branch nick: trunk timestamp: Fri 2013-07-05 09:10:47 -0700 message: * admin/admin.el (make-manuals): Use a pdf/ subdirectory for pdf versions. diff: === modified file 'admin/ChangeLog' --- admin/ChangeLog 2013-07-05 01:35:56 +0000 +++ admin/ChangeLog 2013-07-05 16:10:47 +0000 @@ -1,6 +1,7 @@ 2013-07-05 Glenn Morris * admin.el (make-manuals): Use a standard location for lispintro. + Use a pdf/ subdirectory for pdf versions. 2013-06-29 Glenn Morris === modified file 'admin/admin.el' --- admin/admin.el 2013-07-05 01:35:56 +0000 +++ admin/admin.el 2013-07-05 16:10:47 +0000 @@ -199,7 +199,8 @@ (let* ((dest (expand-file-name "manual" root)) (html-node-dir (expand-file-name "html_node" dest)) (html-mono-dir (expand-file-name "html_mono" dest)) - (ps-dir (expand-file-name "ps" dest))) + (ps-dir (expand-file-name "ps" dest)) + (pdf-dir (expand-file-name "pdf" dest))) (when (file-directory-p dest) (if (y-or-n-p (format "Directory %s exists, delete it first?" dest)) (delete-directory dest t) @@ -208,23 +209,24 @@ (make-directory html-node-dir) (make-directory html-mono-dir) (make-directory ps-dir) + (make-directory pdf-dir) ;; Emacs manual (let ((texi (expand-file-name "doc/emacs/emacs.texi" root))) (manual-html-node texi (expand-file-name "emacs" html-node-dir)) (manual-html-mono texi (expand-file-name "emacs.html" html-mono-dir)) - (manual-pdf texi (expand-file-name "emacs.pdf" dest)) + (manual-pdf texi (expand-file-name "emacs.pdf" pdf-dif)) (manual-ps texi (expand-file-name "emacs.ps" ps-dir))) ;; Lisp manual (let ((texi (expand-file-name "doc/lispref/elisp.texi" root))) (manual-html-node texi (expand-file-name "elisp" html-node-dir)) (manual-html-mono texi (expand-file-name "elisp.html" html-mono-dir)) - (manual-pdf texi (expand-file-name "elisp.pdf" dest)) + (manual-pdf texi (expand-file-name "elisp.pdf" pdf-dir)) (manual-ps texi (expand-file-name "elisp.ps" ps-dir))) ;; Lisp intro. (let ((texi (expand-file-name "doc/lispintro/emacs-lisp-intro.texi" root))) (manual-html-node texi (expand-file-name "eintr" html-node-dir)) (manual-html-mono texi (expand-file-name "eintr.html" html-mono-dir)) - (manual-pdf texi (expand-file-name "eintr.pdf" dest)) + (manual-pdf texi (expand-file-name "eintr.pdf" pdf-dir)) (manual-ps texi (expand-file-name "eintr.ps" ps-dir))) ;; Misc manuals (let ((manuals '("ada-mode" "auth" "autotype" "bovine" "calc" "cc-mode" ------------------------------------------------------------ revno: 113290 committer: Michael Albinus branch nick: trunk timestamp: Fri 2013-07-05 17:17:16 +0200 message: Fix previous patch. diff: === modified file 'lisp/net/tramp-sh.el' --- lisp/net/tramp-sh.el 2013-07-05 13:34:01 +0000 +++ lisp/net/tramp-sh.el 2013-07-05 15:17:16 +0000 @@ -3418,37 +3418,40 @@ (defun tramp-sh-file-gvfs-monitor-dir-process-filter (proc string) "Read output from \"gvfs-monitor-dir\" and add corresponding file-notify events." - (tramp-message proc 6 (format "%S\n%s" proc string)) - (with-current-buffer (process-buffer proc) - (dolist - (line - (split-string string "Directory Monitor Event:[\n\r]+" 'omit-nulls)) - ;; Attribute change is returned in unused wording. - (setq line - (replace-regexp-in-string - "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" line)) - ;; Check, whether there is a problem. - (unless - (string-match - "^Child = \\([^[:blank:]]+\\)[\n\r]+\\(Other = \\([^[:blank:]]+\\)[\n\r]+\\)?Event = \\([^[:blank:]]+\\)[\n\r]+$" line) - (tramp-error proc 'file-notify-error "%s" line)) + (let ((remote-prefix + (with-current-buffer (process-buffer proc) + (file-remote-p default-directory))) + (previous-string (tramp-compat-process-get proc 'previous-string))) + (when previous-string + (tramp-message proc 10 (format "Previous string:\n%s" previous-string))) + (tramp-message proc 6 (format "%S\n%s" proc string)) + (setq string (concat previous-string string) + ;; Attribute change is returned in unused wording. + string (replace-regexp-in-string + "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) - (let* ((remote-prefix (file-remote-p default-directory)) - (object - (list - proc - (intern-soft - (replace-regexp-in-string - "_" "-" (downcase (match-string 4 line)))) - ;; File names are returned as absolute paths. We must - ;; add the remote prefix. - (concat remote-prefix (match-string 1 line)) - (when (match-string 3 line) - (concat remote-prefix (match-string 3 line)))))) + (while (string-match + "^Directory Monitor Event:[\n\r]+Child = \\([^[:blank:]]+\\)[\n\r]+\\(Other = \\([^[:blank:]]+\\)[\n\r]+\\)?Event = \\([^[:blank:]]+\\)[\n\r]+$" string) + (let ((object + (list + proc + (intern-soft + (replace-regexp-in-string + "_" "-" (downcase (match-string 4 string)))) + ;; File names are returned as absolute paths. We must + ;; add the remote prefix. + (concat remote-prefix (match-string 1 string)) + (when (match-string 3 string) + (concat remote-prefix (match-string 3 string)))))) ;; Usually, we would add an Emacs event now. Unfortunately, ;; `unread-command-events' does not accept several events at ;; once. Therefore, we apply the callback directly. - (tramp-compat-funcall 'file-notify-callback object))))) + (tramp-compat-funcall 'file-notify-callback object) + (setq string (replace-match "" nil nil string))))) + + ;; Save rest of the string. + (when string (tramp-message proc 10 (format "Rest string:\n%s" string))) + (tramp-compat-process-put proc 'previous-string string)) (defun tramp-sh-file-inotifywait-process-filter (proc string) "Read output from \"inotifywait\" and add corresponding file-notify events." ------------------------------------------------------------ revno: 113289 committer: Michael Albinus branch nick: trunk timestamp: Fri 2013-07-05 16:06:14 +0200 message: * automated/file-notify-tests.el (file-notify-test-remote-temporary-file-directory): Use `null-device' on w32. (file-notify--test-tmpfile, file-notify--test-tmpfile1) (file-notify--test-results, file-notify--test-event) (file-notify--deftest-remote, file-notify--event-test) (file-notify--test-event-handler) (file-notify--test-make-temp-name): Renamed, in order to mark them internal. (tramp-message-show-message, tramp-read-passwd): Tweak them for better fitting in noninteractive tests. (file-notify-test00-availability): Renamed from `file-notify-test0'. (file-notify-test01-add-watch): Renamed from `file-notify-test1'. Use `temporary-file-directory '. (file-notify-test01-add-watch-remote): New test. (file-notify-test02-events): Renamed from `file-notify-test2'. (file-notify-test02-events-remote): Renamed from `file-notify-test3'. (file-notify-test03-autorevert): Renamed from `file-notify-test4'. Use timeouts. (file-notify-test03-autorevert-remote): Renamed from `file-notify-test5'. diff: === modified file 'test/ChangeLog' --- test/ChangeLog 2013-07-04 09:43:17 +0000 +++ test/ChangeLog 2013-07-05 14:06:14 +0000 @@ -1,3 +1,27 @@ +2013-07-05 Michael Albinus + + * automated/file-notify-tests.el + (file-notify-test-remote-temporary-file-directory): Use + `null-device' on w32. + (file-notify--test-tmpfile, file-notify--test-tmpfile1) + (file-notify--test-results, file-notify--test-event) + (file-notify--deftest-remote, file-notify--event-test) + (file-notify--test-event-handler) + (file-notify--test-make-temp-name): Renamed, in order to mark them + internal. + (tramp-message-show-message, tramp-read-passwd): Tweak them for + better fitting in noninteractive tests. + (file-notify-test00-availability): Renamed from `file-notify-test0'. + (file-notify-test01-add-watch): Renamed from `file-notify-test1'. + Use `temporary-file-directory '. + (file-notify-test01-add-watch-remote): New test. + (file-notify-test02-events): Renamed from `file-notify-test2'. + (file-notify-test02-events-remote): Renamed from `file-notify-test3'. + (file-notify-test03-autorevert): Renamed from + `file-notify-test4'. Use timeouts. + (file-notify-test03-autorevert-remote): Renamed from + `file-notify-test5'. + 2013-07-04 Michael Albinus * automated/file-notify-tests.el: New package. === modified file 'test/automated/file-notify-tests.el' --- test/automated/file-notify-tests.el 2013-07-04 09:43:17 +0000 +++ test/automated/file-notify-tests.el 2013-07-05 14:06:14 +0000 @@ -21,27 +21,77 @@ ;; Some of the tests are intended to run over remote files. Set ;; `file-notify-test-remote-temporary-file-directory' to a suitable -;; value. The remote host must also provide the `inotifywait' program. +;; value. It must NOT require an interactive password prompt, when +;; running the tests in batch mode. + +;; If you want to skip tests for remote files, set this variable to +;; `null-device'. ;;; Code: (require 'ert) (require 'filenotify) -(ert-deftest file-notify-test0 () - "Test availability of \\[file-notify]." +;; There is no default value on w32 systems, which could work out of the box. +(defconst file-notify-test-remote-temporary-file-directory + (if (eq system-type 'windows-nt) null-device "/ssh::/tmp") + "Temporary directory for Tramp tests.") + +(defvar file-notify--test-tmpfile nil) +(defvar file-notify--test-tmpfile1 nil) +(defvar file-notify--test-results nil) +(defvar file-notify--test-event nil) + +(require 'tramp) +(setq tramp-verbose 0 + tramp-message-show-message nil) +(when noninteractive (defalias 'tramp-read-passwd 'ignore)) + +(defmacro file-notify--deftest-remote (test docstring) + "Define ert `TEST-remote' for remote files." + `(when (ignore-errors + (and + (file-remote-p file-notify-test-remote-temporary-file-directory) + (file-directory-p file-notify-test-remote-temporary-file-directory) + (file-writable-p file-notify-test-remote-temporary-file-directory))) + ;; Define the test. + (ert-deftest ,(intern (concat (symbol-name test) "-remote")) () + ,docstring + (let* ((temporary-file-directory + file-notify-test-remote-temporary-file-directory) + (ert-test (ert-get-test ',test)) + (most-recent-result (ert-test-most-recent-result ert-test)) + result) + (unwind-protect + (progn + (setq result + (condition-case err + (ert-run-test ert-test) + ((error quit) + (ert-fail err)))) + (when (ert-test-failed-p result) + (ert-fail + (cadr (ert-test-result-with-condition-condition result))))) + ;; Reset status of TEST. + (setf (ert-test-most-recent-result ert-test) most-recent-result)))))) + +(ert-deftest file-notify-test00-availability () + "Test availability of `file-notify'." (should (memq file-notify-support '(gfilenotify inotify w32notify)))) -(ert-deftest file-notify-test1 () - "Add watch via \\[file-notify-add-watch]." +(ert-deftest file-notify-test01-add-watch () + "Check `file-notify-add-watch'." (let (desc) ;; Check, that different valid parameters are accepted. - (should (setq desc (file-notify-add-watch "/" '(change) 'ignore))) - (file-notify-rm-watch desc) - (should (setq desc (file-notify-add-watch "/" '(attribute-change) 'ignore))) - (file-notify-rm-watch desc) - (should (setq desc (file-notify-add-watch - "/" '(change attribute-change) 'ignore))) + (should (setq desc (file-notify-add-watch + temporary-file-directory '(change) 'ignore))) + (file-notify-rm-watch desc) + (should (setq desc (file-notify-add-watch + temporary-file-directory '(attribute-change) 'ignore))) + (file-notify-rm-watch desc) + (should (setq desc (file-notify-add-watch + temporary-file-directory + '(change attribute-change) 'ignore))) (file-notify-rm-watch desc) ;; Check error handling. @@ -52,121 +102,85 @@ (equal (should-error (file-notify-add-watch 1 2 3)) '(wrong-type-argument 1))) (should - (equal (should-error (file-notify-add-watch "/" 2 3)) + (equal (should-error (file-notify-add-watch temporary-file-directory 2 3)) '(wrong-type-argument 2))) (should - (equal (should-error (file-notify-add-watch "/" '(change) 3)) + (equal (should-error (file-notify-add-watch + temporary-file-directory '(change) 3)) '(wrong-type-argument 3))))) -(defvar file-notify-test-tmpfile nil) -(defvar file-notify-test-tmpfile1 nil) -(defvar file-notify-test-results nil) -(defconst file-notify-test-remote-temporary-file-directory "/ssh::/tmp" - "Temporary directory for Tramp tests.") - -(defvar tramp-verbose) -(setq tramp-verbose 0) -(defvar file-notify--event) - -(defun file-notify-test-run-remote-test () - "Check, whether the remote tests can be run." - (ignore-errors - (and - (file-directory-p file-notify-test-remote-temporary-file-directory) - (file-writable-p file-notify-test-remote-temporary-file-directory)))) - -(defun file-notify-event-test () - "Ert test function to be called by `file-notify-test-event-handler'. -We cannot pass arguments, so we assume that `file-notify--event' +(file-notify--deftest-remote file-notify-test01-add-watch + "Check `file-notify-add-watch' for remote files.") + +(defun file-notify--test-event-test () + "Ert test function to be called by `file-notify--test-event-handler'. +We cannot pass arguments, so we assume that `file-notify--test-event' is bound somewhere." - (message "Event %S" file-notify--event) + ;(message "Event %S" file-notify--test-event) ;; Check the file name. (should - (string-equal (file-notify--event-file-name file-notify--event) - file-notify-test-tmpfile)) + (string-equal (file-notify--event-file-name file-notify--test-event) + file-notify--test-tmpfile)) ;; Check the second file name if exists. - (when (eq (nth 1 file-notify--event) 'renamed) + (when (eq (nth 1 file-notify--test-event) 'renamed) (should (string-equal - (file-notify--event-file1-name file-notify--event) - file-notify-test-tmpfile1)))) - -(defun file-notify-test-event-handler (file-notify--event) - "Run a test over FILE-NOTIFY--EVENT. -Save the result in `file-notify-test-results', for later analysis." - (let ((result (ert-run-test (make-ert-test :body 'file-notify-event-test)))) - (setq file-notify-test-results - (append file-notify-test-results `(,result))))) - -(defun file-notify-test-make-temp-name () + (file-notify--event-file1-name file-notify--test-event) + file-notify--test-tmpfile1)))) + +(defun file-notify--test-event-handler (file-notify--test-event) + "Run a test over FILE-NOTIFY--TEST-EVENT. +Save the result in `file-notify--test-results', for later analysis." + (let ((result + (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) + (setq file-notify--test-results + (append file-notify--test-results `(,result))))) + +(defun file-notify--test-make-temp-name () "Create a temporary file name for test." (expand-file-name (make-temp-name "file-notify-test") temporary-file-directory)) -(ert-deftest file-notify-test2 () +(ert-deftest file-notify-test02-events () "Check file creation/removal notifications." (let (desc) (unwind-protect (progn - (setq file-notify-test-results nil - file-notify-test-tmpfile (file-notify-test-make-temp-name) - file-notify-test-tmpfile1 (file-notify-test-make-temp-name) + (setq file-notify--test-results nil + file-notify--test-tmpfile (file-notify--test-make-temp-name) + file-notify--test-tmpfile1 (file-notify--test-make-temp-name) desc (file-notify-add-watch - file-notify-test-tmpfile - '(change) 'file-notify-test-event-handler)) + file-notify--test-tmpfile + '(change) 'file-notify--test-event-handler)) ;; Check creation and removal. - (write-region "any text" nil file-notify-test-tmpfile) - (delete-file file-notify-test-tmpfile) + (write-region "any text" nil file-notify--test-tmpfile) + (delete-file file-notify--test-tmpfile) ;; Check copy and rename. - (write-region "any text" nil file-notify-test-tmpfile) - (copy-file file-notify-test-tmpfile file-notify-test-tmpfile1) - (delete-file file-notify-test-tmpfile) - (delete-file file-notify-test-tmpfile1) + (write-region "any text" nil file-notify--test-tmpfile) + (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) + (delete-file file-notify--test-tmpfile) + (delete-file file-notify--test-tmpfile1) - (write-region "any text" nil file-notify-test-tmpfile) - (rename-file file-notify-test-tmpfile file-notify-test-tmpfile1) - (delete-file file-notify-test-tmpfile1)) + (write-region "any text" nil file-notify--test-tmpfile) + (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) + (delete-file file-notify--test-tmpfile1)) ;; Wait for events, and exit. (sit-for 5 'nodisplay) (file-notify-rm-watch desc) - (ignore-errors (delete-file file-notify-test-tmpfile)) - (ignore-errors (delete-file file-notify-test-tmpfile1)))) + (ignore-errors (delete-file file-notify--test-tmpfile)) + (ignore-errors (delete-file file-notify--test-tmpfile1)))) - (dolist (result file-notify-test-results) + (dolist (result file-notify--test-results) ;(message "%s" (ert-test-result-messages result)) (when (ert-test-failed-p result) (ert-fail (cadr (ert-test-result-with-condition-condition result)))))) -;; TODO: When the remote test fails, suppress FAILED indication for TEST. -(defmacro file-notify-test-remote (test) - "Run ert TEST for remote files." - `(let* ((temporary-file-directory - file-notify-test-remote-temporary-file-directory) - (ert-test (ert-get-test ,test)) - (most-recent-result (ert-test-most-recent-result ert-test)) - result) - (unwind-protect - (progn - (setq result - (condition-case err - (ert-run-test (ert-get-test ,test)) - ((error quit) - (ert-fail err)))) - (when (ert-test-failed-p result) - (ert-fail - (cadr (ert-test-result-with-condition-condition result))))) - ;; Reset status of TEST. - (setf (ert-test-most-recent-result ert-test) most-recent-result)))) - -(when (file-notify-test-run-remote-test) - (ert-deftest file-notify-test3 () - "Check file creation/removal notification for remote files." - (file-notify-test-remote 'file-notify-test2)) -) ;; (file-notify-test-run-remote-test) +(file-notify--deftest-remote file-notify-test02-events + "Check file creation/removal notifications for remote files.") ;; autorevert runs only in interactive mode. (defvar auto-revert-remote-files) @@ -174,50 +188,58 @@ (require 'autorevert) (when (null noninteractive) - (ert-deftest file-notify-test4 () + (ert-deftest file-notify-test03-autorevert () "Check autorevert via file notification. This test is skipped in batch mode." ;; `auto-revert-buffers' runs every 5". And we must wait, until ;; the file has been reverted. - (let ((wait 10) + (let ((timeout 10) buf) (unwind-protect (progn - (setq file-notify-test-tmpfile (file-notify-test-make-temp-name)) + (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify-test-tmpfile) - (setq buf (find-file-noselect file-notify-test-tmpfile)) + (write-region "any text" nil file-notify--test-tmpfile) + (setq buf (find-file-noselect file-notify--test-tmpfile)) (with-current-buffer buf (should (string-equal (buffer-string) "any text")) (auto-revert-mode 1) + ;; `auto-revert-buffers' runs every 5". - (sit-for wait) + (with-timeout (timeout (ignore)) + (while (null auto-revert-notify-watch-descriptor) + (sit-for 0.1 'nodisplay))) ;; Check, that file notification has been used. (should auto-revert-mode) (should auto-revert-use-notify) (should auto-revert-notify-watch-descriptor) - ;; Modify file. + ;; Modify file. We wait for a second, in order to + ;; have another timestamp. + (sit-for 1) (shell-command (format "echo -n 'another text' >%s" - (or (file-remote-p file-notify-test-tmpfile 'localname) - file-notify-test-tmpfile))) - (sit-for wait) + (or (file-remote-p file-notify--test-tmpfile 'localname) + file-notify--test-tmpfile))) ;; Check, that the buffer has been reverted. + (with-current-buffer (get-buffer-create "*Messages*") + (with-timeout (timeout (ignore)) + (while + (null (string-match + (format "Reverting buffer `%s'." (buffer-name buf)) + (buffer-string))) + (sit-for 0.1 'nodisplay)))) (should (string-equal (buffer-string) "another text")))) ;; Exit. (ignore-errors (kill-buffer buf)) - (ignore-errors (delete-file file-notify-test-tmpfile))))) + (ignore-errors (delete-file file-notify--test-tmpfile))))) - (when (file-notify-test-run-remote-test) - (ert-deftest file-notify-test5 () - "Check autorevert via file notification for remote files. -This test is skipped in batch mode." - (file-notify-test-remote 'file-notify-test4)) - ) ;; (file-notify-test-run-remote-test) + (file-notify--deftest-remote file-notify-test03-autorevert + "Check autorevert via file notification for remote files. +This test is skipped in batch mode.") ) ;; (null noninteractive) (defun file-notify-test-all (&optional interactive) ------------------------------------------------------------ revno: 113288 fixes bug: http://debbugs.gnu.org/14688 committer: Stephen Berman branch nick: trunk timestamp: Fri 2013-07-05 16:03:35 +0200 message: * calendar/todo-mode.el: Add handling of file deletion, both by mode command and externally. Fix various related bugs. Clarify Commentary and improve some documentation strings and code. (todo-delete-file): New command. (todo-check-file): New function. (todo-show): Handle external deletion of the file we're trying to show. Replace called-interactively-p by an optional prefix argument to avoid problematic interaction with catch form when byte compiled (bug#14702). (todo-quit): Handle external deletion of the archive's todo file. Make sure the buffer that was visiting the archive file is still live before trying to bury it. (todo-category-completions): Handle external deletion of any category completion files. (todo-jump-to-category, todo-basic-insert-item): Recalculate list of todo files, in case of external deletion. (todo-add-file): Replace unnecessary setq by let-binding. (todo-find-archive): Check whether there are any archives. Replace unnecessary setq by let-binding. (todo-archive-done-item): Use find-file-noselect to get the archive buffer whether or not the archive already exists. Remove superfluous code. Use file size instead of buffer-file-name to check if the archive is new; if it is, update list of archives. (todo-default-todo-file): Allow nil to be a valid value for when there are no todo files. (todo-reevaluate-default-file-defcustom): Use corrected definition of todo-default-todo-file. (todo-key-bindings-t+a+f): Add key binding for todo-delete-file. (todo-delete-category, todo-show-categories-table) (todo-category-number): Clarify comment. (todo-filter-items): Clarify documentation string. (todo-show-current-file, todo-display-as-todo-file) (todo-reset-and-enable-done-separator): Tweak documentation string. (todo-done-separator): Make separator length window-width, since bug#2749 is now fixed. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-07-05 13:34:01 +0000 +++ lisp/ChangeLog 2013-07-05 14:03:35 +0000 @@ -1,3 +1,41 @@ +2013-07-05 Stephen Berman + + * calendar/todo-mode.el: Add handling of file deletion, both by + mode command and externally. Fix various related bugs. Clarify + Commentary and improve some documentation strings and code. + (todo-delete-file): New command. + (todo-check-file): New function. + (todo-show): Handle external deletion of the file we're trying to + show (bug#14688). Replace called-interactively-p by an optional + prefix argument to avoid problematic interaction with catch form + when byte compiled (bug#14702). + (todo-quit): Handle external deletion of the archive's todo file. + Make sure the buffer that was visiting the archive file is still + live before trying to bury it. + (todo-category-completions): Handle external deletion of any + category completion files. + (todo-jump-to-category, todo-basic-insert-item): Recalculate list + of todo files, in case of external deletion. + (todo-add-file): Replace unnecessary setq by let-binding. + (todo-find-archive): Check whether there are any archives. + Replace unnecessary setq by let-binding. + (todo-archive-done-item): Use find-file-noselect to get the + archive buffer whether or not the archive already exists. Remove + superfluous code. Use file size instead of buffer-file-name to + check if the archive is new; if it is, update list of archives. + (todo-default-todo-file): Allow nil to be a valid value for when + there are no todo files. + (todo-reevaluate-default-file-defcustom): Use corrected definition + of todo-default-todo-file. + (todo-key-bindings-t+a+f): Add key binding for todo-delete-file. + (todo-delete-category, todo-show-categories-table) + (todo-category-number): Clarify comment. + (todo-filter-items): Clarify documentation string. + (todo-show-current-file, todo-display-as-todo-file) + (todo-reset-and-enable-done-separator): Tweak documentation string. + (todo-done-separator): Make separator length window-width, since + bug#2749 is now fixed. + 2013-07-05 Michael Albinus * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support === modified file 'lisp/calendar/todo-mode.el' --- lisp/calendar/todo-mode.el 2013-06-30 15:10:33 +0000 +++ lisp/calendar/todo-mode.el 2013-07-05 14:03:35 +0000 @@ -37,11 +37,14 @@ ;; can edit todo items, reprioritize them within their category, move ;; them to another category, delete them, or mark items as done and ;; store them separately from the not yet done items in a category. -;; You can add new todo files and categories, rename categories, move -;; them to another file or delete them. You can also display summary -;; tables of the categories in a file and the types of items they -;; contain. And you can build cross-category lists of items that -;; satisfy various criteria. +;; You can add new todo files, edit and delete them. You can add new +;; categories, rename and delete them, move categories to another file +;; and merge the items of two categories. You can also reorder the +;; sequence of categories in a todo file for the purpose of +;; navigation. You can display summary tables of the categories in a +;; file and the types of items they contain. And you can compile +;; lists of existing items from multiple categories in one or more +;; todo files, which are filtered by various criteria. ;; To get started, load this package and type `M-x todo-show'. This ;; will prompt you for the name of the first todo file, its first @@ -169,12 +172,7 @@ "Return string used as value of variable `todo-done-separator'." (let ((sep todo-done-separator-string)) (propertize (if (= 1 (length sep)) - ;; Until bug#2749 is fixed, if separator's length - ;; is window-width and todo-wrap-lines is - ;; non-nil, an indented empty line appears between - ;; the separator and the first done item. - ;; (make-string (window-width) (string-to-char sep)) - (make-string (1- (window-width)) (string-to-char sep)) + (make-string (window-width) (string-to-char sep)) todo-done-separator-string) 'face 'todo-done-sep))) @@ -578,11 +576,12 @@ (file-name-sans-extension (file-name-nondirectory file)))) (defcustom todo-default-todo-file (todo-short-file-name - (car (funcall todo-files-function))) + (car (funcall todo-files-function))) "Todo file visited by first session invocation of `todo-show'." - :type `(radio ,@(mapcar (lambda (f) (list 'const f)) - (mapcar 'todo-short-file-name - (funcall todo-files-function)))) + :type (when todo-files + `(radio ,@(mapcar (lambda (f) (list 'const f)) + (mapcar 'todo-short-file-name + (funcall todo-files-function))))) :group 'todo) (defcustom todo-show-current-file t @@ -630,7 +629,7 @@ :group 'todo) ;;;###autoload -(defun todo-show (&optional solicit-file) +(defun todo-show (&optional solicit-file interactive) "Visit a todo file and display one of its categories. When invoked in Todo mode, prompt for which todo file to visit. @@ -668,117 +667,124 @@ Invoking this command in Todo Archive mode visits the corresponding todo file, displaying the corresponding category." - (interactive "P") + (interactive "P\np") + (when todo-default-todo-file + (todo-check-file (todo-absolute-file-name todo-default-todo-file))) (catch 'shown - ;; If there is a legacy todo file but no todo file in the current - ;; format, offer to convert the legacy file and show it. + ;; Before initializing the first todo first, check if there is a + ;; legacy todo file and if so, offer to convert to the current + ;; format and make it the first new todo file. (unless todo-default-todo-file (let ((legacy-todo-file (if (boundp 'todo-file-do) - todo-file-do - (locate-user-emacs-file "todo-do" ".todo-do")))) - (when (and (file-exists-p legacy-todo-file) - (y-or-n-p (concat "Do you want to convert a copy of your " - "old todo file to the new format? "))) - (when (todo-convert-legacy-files) - (throw 'shown nil))))) - (let* ((cat) - (show-first todo-show-first) - (file (cond ((or solicit-file - (and (called-interactively-p 'any) - (memq major-mode '(todo-mode - todo-archive-mode - todo-filtered-items-mode)))) - (if (funcall todo-files-function) - (todo-read-file-name "Choose a todo file to visit: " - nil t) - (user-error "There are no todo files"))) - ((and (eq major-mode 'todo-archive-mode) - ;; Called noninteractively via todo-quit - ;; to jump to corresponding category in - ;; todo file. - (not (called-interactively-p 'any))) - (setq cat (todo-current-category)) - (concat (file-name-sans-extension - todo-current-todo-file) ".todo")) - (t - (or todo-current-todo-file - (and todo-show-current-file - todo-global-current-todo-file) - (todo-absolute-file-name todo-default-todo-file) - (todo-add-file))))) - add-item first-file) - (unless todo-default-todo-file - ;; We just initialized the first todo file, so make it the default. - (setq todo-default-todo-file (todo-short-file-name file) - first-file t) - (todo-reevaluate-default-file-defcustom)) - (unless (member file todo-visited) - ;; Can't setq t-c-t-f here, otherwise wrong file shown when - ;; todo-show is called from todo-show-categories-table. - (let ((todo-current-todo-file file)) - (cond ((eq todo-show-first 'table) - (todo-show-categories-table)) - ((memq todo-show-first '(top diary regexp)) - (let* ((shortf (todo-short-file-name file)) - (fi-file (todo-absolute-file-name - shortf todo-show-first))) - (when (eq todo-show-first 'regexp) - (let ((rxfiles (directory-files todo-directory t - ".*\\.todr$" t))) - (when (and rxfiles (> (length rxfiles) 1)) - (let ((rxf (mapcar 'todo-short-file-name rxfiles))) - (setq fi-file (todo-absolute-file-name - (completing-read - "Choose a regexp items file: " - rxf) 'regexp)))))) - (if (file-exists-p fi-file) - (set-window-buffer - (selected-window) - (set-buffer (find-file-noselect fi-file 'nowarn))) - (message "There is no %s file for %s" - (cond ((eq todo-show-first 'top) - "top priorities") - ((eq todo-show-first 'diary) - "diary items") - ((eq todo-show-first 'regexp) - "regexp items")) - shortf) - (setq todo-show-first 'first))))))) - (when (or (member file todo-visited) - (eq todo-show-first 'first)) - (set-window-buffer (selected-window) - (set-buffer (find-file-noselect file 'nowarn))) - ;; When quitting an archive file, show the corresponding - ;; category in the corresponding todo file, if it exists. - (when (assoc cat todo-categories) - (setq todo-category-number (todo-category-number cat))) - ;; If this is a new todo file, add its first category. - (when (zerop (buffer-size)) - (let (cat-added) - (unwind-protect - (setq todo-category-number - (todo-add-category todo-current-todo-file "") - add-item todo-add-item-if-new-category - cat-added t) - (if cat-added - ;; If the category was added, save the file now, so we - ;; don't risk having an empty todo file, which would - ;; signal an error if we tried to visit it later, - ;; since doing that looks for category boundaries. - (save-buffer 0) - ;; If user cancels before adding the category, clean up - ;; and exit, so we have a fresh slate the next time. - (delete-file file) - (setq todo-files (delete file todo-files)) - (when first-file - (setq todo-default-todo-file nil - todo-current-todo-file nil)) - (kill-buffer) - (keyboard-quit))))) - (save-excursion (todo-category-select)) - (when add-item (todo-basic-insert-item))) - (setq todo-show-first show-first) - (add-to-list 'todo-visited file)))) + todo-file-do + (locate-user-emacs-file "todo-do" ".todo-do")))) + (when (and (file-exists-p legacy-todo-file) + (y-or-n-p (concat "Do you want to convert a copy of your " + "old todo file to the new format? "))) + (when (todo-convert-legacy-files) + (throw 'shown nil))))) + (catch 'end + (let* ((cat) + (show-first todo-show-first) + (file (cond ((or solicit-file + (and interactive + (memq major-mode '(todo-mode + todo-archive-mode + todo-filtered-items-mode)))) + (if (funcall todo-files-function) + (todo-read-file-name "Choose a todo file to visit: " + nil t) + (user-error "There are no todo files"))) + ((and (eq major-mode 'todo-archive-mode) + ;; Called noninteractively via todo-quit + ;; to jump to corresponding category in + ;; todo file. + (not interactive)) + (setq cat (todo-current-category)) + (concat (file-name-sans-extension + todo-current-todo-file) ".todo")) + (t + (or todo-current-todo-file + (and todo-show-current-file + todo-global-current-todo-file) + (todo-absolute-file-name todo-default-todo-file) + (todo-add-file))))) + add-item first-file) + (unless todo-default-todo-file + ;; We just initialized the first todo file, so make it the default. + (setq todo-default-todo-file (todo-short-file-name file) + first-file t) + (todo-reevaluate-default-file-defcustom)) + (unless (member file todo-visited) + ;; Can't setq t-c-t-f here, otherwise wrong file shown when + ;; todo-show is called from todo-show-categories-table. + (let ((todo-current-todo-file file)) + (cond ((eq todo-show-first 'table) + (todo-show-categories-table)) + ((memq todo-show-first '(top diary regexp)) + (let* ((shortf (todo-short-file-name file)) + (fi-file (todo-absolute-file-name + shortf todo-show-first))) + (when (eq todo-show-first 'regexp) + (let ((rxfiles (directory-files todo-directory t + ".*\\.todr$" t))) + (when (and rxfiles (> (length rxfiles) 1)) + (let ((rxf (mapcar 'todo-short-file-name rxfiles))) + (setq fi-file (todo-absolute-file-name + (completing-read + "Choose a regexp items file: " + rxf) 'regexp)))))) + (if (file-exists-p fi-file) + (set-window-buffer + (selected-window) + (set-buffer (find-file-noselect fi-file 'nowarn))) + (message "There is no %s file for %s" + (cond ((eq todo-show-first 'top) + "top priorities") + ((eq todo-show-first 'diary) + "diary items") + ((eq todo-show-first 'regexp) + "regexp items")) + shortf) + (setq todo-show-first 'first))))))) + (when (or (member file todo-visited) + (eq todo-show-first 'first)) + (unless (todo-check-file file) (throw 'end nil)) + (set-window-buffer (selected-window) + (set-buffer (find-file-noselect file 'nowarn))) + ;; When quitting an archive file, show the corresponding + ;; category in the corresponding todo file, if it exists. + (when (assoc cat todo-categories) + (setq todo-category-number (todo-category-number cat))) + ;; If this is a new todo file, add its first category. + (when (zerop (buffer-size)) + (let (cat-added) + (unwind-protect + (setq todo-category-number + (todo-add-category todo-current-todo-file "") + add-item todo-add-item-if-new-category + cat-added t) + (if cat-added + ;; If the category was added, save the file now, so we + ;; don't risk having an empty todo file, which would + ;; signal an error if we tried to visit it later, + ;; since doing that looks for category boundaries. + (save-buffer 0) + ;; If user cancels before adding the category, clean up + ;; and exit, so we have a fresh slate the next time. + (delete-file file) + ;; (setq todo-files (funcall todo-files-function)) + (setq todo-files (delete file todo-files)) + (when first-file + (setq todo-default-todo-file nil + todo-current-todo-file nil) + (todo-reevaluate-default-file-defcustom)) + (kill-buffer) + (keyboard-quit))))) + (save-excursion (todo-category-select)) + (when add-item (todo-basic-insert-item))) + (setq todo-show-first show-first) + (add-to-list 'todo-visited file))))) (defun todo-save () "Save the current todo file." @@ -814,8 +820,15 @@ ;; Have to write a newly created archive to file to avoid ;; subsequent errors. (todo-save) - (todo-show) - (bury-buffer buf)) + (let ((todo-file (concat todo-directory + (todo-short-file-name todo-current-todo-file) + ".todo"))) + (if (todo-check-file todo-file) + (todo-show) + (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))) ((eq major-mode 'todo-mode) (todo-save) ;; If we just quit archive mode, just burying the buffer @@ -893,7 +906,7 @@ (interactive "P") ;; If invoked outside of Todo mode and there is not yet any Todo ;; file, initialize one. - (if (null todo-files) + (if (null (funcall todo-files-function)) (todo-show) (let* ((archive (eq where 'archive)) (cat (unless archive where)) @@ -1069,10 +1082,9 @@ prompt for the first item. Noninteractively, return the name of the new file." (interactive) - (let ((prompt (concat "Enter name of new todo file " - "(TAB or SPC to see current names): ")) - file) - (setq file (todo-read-file-name prompt)) + (let* ((prompt (concat "Enter name of new todo file " + "(TAB or SPC to see current names): ")) + (file (todo-read-file-name prompt))) (with-current-buffer (get-buffer-create file) (erase-buffer) (write-region (point-min) (point-max) file nil 'nomessage nil t) @@ -1087,6 +1099,55 @@ (todo-show)) file))) +(defun todo-delete-file () + "Delete the current todo, archive or filtered items file. +If the todo file has a corresponding archive file, or vice versa, +prompt whether to delete that as well. Also kill the buffers +visiting the deleted files." + (interactive) + (let* ((file1 (buffer-file-name)) + (todo (eq major-mode 'todo-mode)) + (archive (eq major-mode 'todo-archive-mode)) + (filtered (eq major-mode 'todo-filtered-items-mode)) + (file1-sn (todo-short-file-name file1)) + (file2 (concat todo-directory file1-sn (cond (todo ".toda") + (archive ".todo")))) + (buf1 (current-buffer)) + (buf2 (when file2 (find-buffer-visiting file2))) + (prompt1 (concat "Delete " (cond (todo "todo") + (archive "archive") + (filtered "filtered items")) + " file \"%s\"? ")) + (prompt2 (concat "Also delete the corresponding " + (cond (todo "archive") (archive "todo")) " file " + (when buf2 "and kill the buffer visiting it? "))) + (delete1 (yes-or-no-p (format prompt1 file1-sn))) + (delete2 (when (and delete1 (or (file-exists-p file2) buf2)) + (yes-or-no-p prompt2)))) + (when delete1 + (when (file-exists-p file1) (delete-file file1)) + (setq todo-visited (delete file1 todo-visited)) + (kill-buffer buf1) + (when delete2 + (when (file-exists-p file2) (delete-file file2)) + (setq todo-visited (delete file2 todo-visited)) + (and buf2 (kill-buffer buf2))) + (setq todo-files (funcall todo-files-function) + todo-archives (funcall todo-files-function t)) + (when (or (string= file1-sn todo-default-todo-file) + (and delete2 (string= file1-sn todo-default-todo-file))) + (setq todo-default-todo-file (todo-short-file-name (car todo-files)))) + (when (or (string= file1 todo-global-current-todo-file) + (and delete2 (string= file2 todo-global-current-todo-file))) + (setq todo-global-current-todo-file nil)) + (todo-reevaluate-filelist-defcustoms) + (message (concat (cond (todo "Todo") (archive "Archive")) " file \"%s\" " + (when delete2 + (concat "and its " + (cond (todo "archive") (archive "todo")) + " file ")) + "deleted") file1-sn)))) + (defvar todo-edit-buffer "*Todo Edit*" "Name of current buffer in Todo Edit mode.") @@ -1190,9 +1251,9 @@ (save-excursion (todo-category-select))) (defun todo-delete-category (&optional arg) - "Delete current todo category provided it is empty. -With ARG non-nil delete the category unconditionally, -i.e. including all existing todo and done items." + "Delete current todo category provided it contains no items. +With prefix ARG delete the category even if it does contain +todo or done items." (interactive "P") (let* ((file todo-current-todo-file) (cat (todo-current-category)) @@ -1723,7 +1784,7 @@ the item accordingly." ;; If invoked outside of Todo mode and there is not yet any Todo ;; file, initialize one. - (if (null todo-files) + (if (null (funcall todo-files-function)) (todo-show) (let ((region (eq region-or-here 'region)) (here (eq region-or-here 'here))) @@ -2958,31 +3019,32 @@ archive, subsequent visits return to the last category displayed." (interactive) - (let* ((cat (todo-current-category)) - (count (todo-get-count 'archived cat)) - (archive (concat (file-name-sans-extension todo-current-todo-file) - ".toda")) - place) - (setq place (cond (ask 'other-archive) - ((file-exists-p archive) 'this-archive) - (t (when (todo-y-or-n-p - (concat "This file has no archive; " - "visit another archive? ")) - 'other-archive)))) - (when (eq place 'other-archive) - (setq archive (todo-read-file-name "Choose a todo archive: " t t))) - (when (and (eq place 'this-archive) (zerop count)) - (setq place (when (todo-y-or-n-p - (concat "This category has no archived items;" - " visit archive anyway? ")) - 'other-cat))) - (when place - (set-window-buffer (selected-window) - (set-buffer (find-file-noselect archive))) - (if (member place '(other-archive other-cat)) - (setq todo-category-number 1) - (todo-category-number cat)) - (todo-category-select)))) + (if (null (funcall todo-files-function t)) + (message "There are no archive files") + (let* ((cat (todo-current-category)) + (count (todo-get-count 'archived cat)) + (archive (concat (file-name-sans-extension todo-current-todo-file) + ".toda")) + (place (cond (ask 'other-archive) + ((file-exists-p archive) 'this-archive) + (t (when (todo-y-or-n-p + (concat "This file has no archive; " + "visit another archive? ")) + 'other-archive))))) + (when (eq place 'other-archive) + (setq archive (todo-read-file-name "Choose a todo archive: " t t))) + (when (and (eq place 'this-archive) (zerop count)) + (setq place (when (todo-y-or-n-p + (concat "This category has no archived items;" + " visit archive anyway? ")) + 'other-cat))) + (when place + (set-window-buffer (selected-window) + (set-buffer (find-file-noselect archive))) + (if (member place '(other-archive other-cat)) + (setq todo-category-number 1) + (todo-category-number cat)) + (todo-category-select))))) (defun todo-choose-archive () "Choose an archive and visit it." @@ -3010,9 +3072,7 @@ (marked (assoc cat todo-categories-with-marks)) (afile (concat (file-name-sans-extension todo-current-todo-file) ".toda")) - (archive (if (file-exists-p afile) - (find-file-noselect afile t) - (get-buffer-create afile))) + (archive (find-file-noselect afile t)) (item (and (todo-done-item-p) (concat (todo-item-string) "\n"))) (count 0) @@ -3056,7 +3116,6 @@ (if (not (or marked all item)) (throw 'end (message "Only done items can be archived")) (with-current-buffer archive - (unless buffer-file-name (erase-buffer)) (let (buffer-read-only) (widen) (goto-char (point-min)) @@ -3076,11 +3135,13 @@ (item))) (todo-update-count 'done (if (or marked all) count 1) cat) (todo-update-categories-sexp) - ;; If archive is new, save to file now (using write-region in - ;; order not to get prompted for file to save to), to let - ;; auto-mode-alist take effect below. - (unless buffer-file-name - (write-region nil nil afile) + ;; If archive is new, save to file now (with + ;; write-region to avoid prompt for file to save to) + ;; to update todo-archives, and to let auto-mode-alist + ;; take effect below on visiting the archive. + (unless (nth 7 (file-attributes afile)) + (write-region nil nil afile t t) + (setq todo-archives (funcall todo-files-function t)) (kill-buffer)))) (with-current-buffer tbuf (cond @@ -3286,19 +3347,24 @@ (defun todo-show-categories-table () "Display a table of the current file's categories and item counts. -In the initial display the categories are numbered, indicating -their current order for navigating by \\[todo-forward-category] -and \\[todo-backward-category]. You can permanently change the -order of the category at point by typing -\\[todo-set-category-number], \\[todo-raise-category] or -\\[todo-lower-category]. +In the initial display the lines of the table are numbered, +indicating the current order of the categories when sequentially +navigating through the todo file with `\\[todo-forward-category]' +and `\\[todo-backward-category]'. You can reorder the lines, and +hence the category sequence, by typing `\\[todo-raise-category]' +or `\\[todo-lower-category]' to raise or lower the category at +point, or by typing `\\[todo-set-category-number]' and entering a +number at the prompt or by typing `\\[todo-set-category-number]' +with a numeric prefix. If you save the todo file after +reordering the categories, the new order persists in subsequent +Emacs sessions. The labels above the category names and item counts are buttons, and clicking these changes the display: sorted by category name or by the respective item counts (alternately descending or ascending). In these displays the categories are not numbered -and \\[todo-set-category-number], \\[todo-raise-category] and -\\[todo-lower-category] are disabled. (Programmatically, the +and `\\[todo-set-category-number]', `\\[todo-raise-category]' and +`\\[todo-lower-category]' are disabled. (Programmatically, the sorting is triggered by passing a non-nil SORTKEY argument.) In addition, the lines with the category names and item counts @@ -4019,15 +4085,15 @@ "Buffer type string for `todo-filter-items'.") (defun todo-filter-items (filter &optional new multifile) - "Display a cross-category list of items filtered by FILTER. + "Display a list of items filtered by FILTER. The values of FILTER can be `top' for top priority items, a cons of `top' and a number passed by the caller, `diary' for diary -items, or `regexp' for items matching a regular expression entered -by the user. The items can be from any categories in the current -todo file or, with non-nil MULTIFILE, from several files. If NEW -is nil, visit an appropriate file containing the list of filtered -items; if there is no such file, or with non-nil NEW, build the -list and display it. +items, or `regexp' for items matching a regular expression +entered by the user. The items can come from any categories in +the current todo file or, with non-nil MULTIFILE, from several +files. If NEW is nil, visit an appropriate file containing the +list of filtered items; if there is no such file, or with non-nil +NEW, build the list and display it. See the documentation strings of the commands `todo-filter-top-priorities', `todo-filter-diary-items', @@ -4699,14 +4765,57 @@ ((eq type 'regexp) ".todr") (t ".todo")))))) +(defun todo-check-file (file) + "Check the state associated with FILE and update it if necessary. +If FILE exists, return t. If it does not exist and there is no +live buffer with its content, return nil; if there is such a +buffer and the user tries to show it, ask whether to restore +FILE, and if confirmed, do so and return t; else delete the +buffer, clean up the state and return nil." + (setq todo-files (funcall todo-files-function)) + (setq todo-archives (funcall todo-files-function t)) + (if (file-exists-p file) + t + (setq todo-visited (delete file todo-visited)) + (let ((buf (find-buffer-visiting file))) + (if (and buf + (y-or-n-p + (concat + (format (concat "Todo file \"%s\" has been deleted but " + "its content is still in a buffer!\n") + (todo-short-file-name file)) + "Save that buffer and restore the todo file? "))) + (progn + (with-current-buffer buf (save-buffer)) + (setq todo-files (funcall todo-files-function)) + (setq todo-archives (funcall todo-files-function t)) + t) + (let* ((files (append todo-files todo-archives)) + (tctf todo-current-todo-file) + (tgctf todo-global-current-todo-file) + (tdtf (todo-absolute-file-name todo-default-todo-file))) + (unless (or (not todo-current-todo-file) + (member todo-current-todo-file files)) + (setq todo-current-todo-file nil)) + (unless (or (not todo-global-current-todo-file) + (member todo-global-current-todo-file files)) + (setq todo-global-current-todo-file nil)) + (unless (or (not todo-default-todo-file) + (member todo-default-todo-file files)) + (setq todo-default-todo-file (todo-short-file-name + (car todo-files)))) + (todo-reevaluate-filelist-defcustoms) + (when buf (kill-buffer buf)) + nil))))) + (defun todo-category-number (cat) "Return the number of category CAT in this todo file. The buffer-local variable `todo-category-number' holds this number as its value." (let ((categories (mapcar 'car todo-categories))) (setq todo-category-number - ;; Increment by one, so that the highest priority category in Todo - ;; Categories mode is numbered one rather than zero. + ;; Increment by one, so that the number of the first + ;; category is one rather than zero. (1+ (- (length categories) (length (member cat categories))))))) @@ -5384,7 +5493,27 @@ file or list of files (as short file names) it is in. The files are either the current (or if there is none, the default) todo file plus the files listed in `todo-category-completions-files', -or, with non-nil ARCHIVE, the current archive file." +or, with non-nil ARCHIVE, the current archive file. + +Before calculating the completions, update the value of +`todo-category-completions-files' in case any files named in it +have been removed." + (let (deleted) + (dolist (f todo-category-completions-files) + (unless (file-exists-p (todo-absolute-file-name f)) + (setq todo-category-completions-files + (delete f todo-category-completions-files)) + (push f deleted))) + (when deleted + (let ((pl (> (length deleted) 1)) + (names (mapconcat (lambda (f) (concat "\"" f "\"")) deleted ", "))) + (message (concat "File" (if pl "s" "") " " names " ha" (if pl "ve" "s") + " been deleted and removed from\n" + "the list of category completion files"))) + (todo-reevaluate-category-completions-files-defcustom) + (custom-set-default 'todo-category-completions-files + (symbol-value 'todo-category-completions-files)) + (sleep-for 1.5))) (let* ((curfile (or todo-current-todo-file (and todo-show-current-file todo-global-current-todo-file) @@ -5435,6 +5564,7 @@ otherwise, a new file name is allowed." (let* ((completion-ignore-case todo-completion-ignore-case) (files (mapcar 'todo-short-file-name + ;; (funcall todo-files-function archive))) (if archive todo-archives todo-files))) (file (completing-read prompt files nil mustmatch nil nil (if files @@ -5529,7 +5659,7 @@ ;; Validate only against completion categories. (let ((todo-categories categories)) (setq cat (todo-validate-name cat 'category))) - ;; When user enters a nonexistest category name by jumping or + ;; When user enters a nonexistent category name by jumping or ;; moving, confirm that it should be added, then validate. (unless add (if (todo-y-or-n-p (format "Add new category \"%s\" to file \"%s\"? " @@ -5867,13 +5997,24 @@ (defun todo-reevaluate-default-file-defcustom () "Reevaluate defcustom of `todo-default-todo-file'. -Called after adding or deleting a todo file." - (eval (defcustom todo-default-todo-file (car (funcall todo-files-function)) - "Todo file visited by first session invocation of `todo-show'." - :type `(radio ,@(mapcar (lambda (f) (list 'const f)) - (mapcar 'todo-short-file-name - (funcall todo-files-function)))) - :group 'todo))) +Called after adding or deleting a todo file. If the value of +`todo-default-todo-file' before calling this function was +associated with an existing file, keep that value." + ;; (let ((curval todo-default-todo-file)) + (eval + (defcustom todo-default-todo-file (todo-short-file-name + (car (funcall todo-files-function))) + "Todo file visited by first session invocation of `todo-show'." + :type (when todo-files + `(radio ,@(mapcar (lambda (f) (list 'const f)) + (mapcar 'todo-short-file-name + (funcall todo-files-function))))) + :group 'todo)) + ;; (when (and curval (file-exists-p (todo-absolute-file-name curval))) + ;; (custom-set-default 'todo-default-todo-file curval) + ;; ;; (custom-reevaluate-setting 'todo-default-todo-file) + ;; ))) + ) (defun todo-reevaluate-category-completions-files-defcustom () "Reevaluate defcustom of `todo-category-completions-files'. @@ -6060,6 +6201,7 @@ ("Cu" todo-unmark-category) ("Fh" todo-toggle-item-header) ("h" todo-toggle-item-header) + ("Fk" todo-delete-file) ("Fe" todo-edit-file) ("FH" todo-toggle-item-highlighting) ("H" todo-toggle-item-highlighting) @@ -6226,12 +6368,13 @@ (defun todo-show-current-file () "Visit current instead of default todo file with `todo-show'. -This function is added to `pre-command-hook' when user option +Added to `pre-command-hook' in Todo mode when user option `todo-show-current-file' is set to non-nil." (setq todo-global-current-todo-file todo-current-todo-file)) (defun todo-display-as-todo-file () - "Show todo files correctly when visited from outside of Todo mode." + "Show todo files correctly when visited from outside of Todo mode. +Added to `find-file-hook' in Todo mode and Todo Archive mode." (and (member this-command todo-visit-files-commands) (= (- (point-max) (point-min)) (buffer-size)) (member major-mode '(todo-mode todo-archive-mode)) @@ -6265,7 +6408,7 @@ (defun todo-reset-and-enable-done-separator () "Show resized done items separator overlay after window change. -Added to `window-configuration-change-hook' in `todo-mode'." +Added to `window-configuration-change-hook' in Todo mode." (when (= 1 (length todo-done-separator-string)) (let ((sep todo-done-separator)) (setq todo-done-separator (todo-done-separator)) ------------------------------------------------------------ revno: 113287 committer: Michael Albinus branch nick: trunk timestamp: Fri 2013-07-05 15:34:01 +0200 message: * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support both "gvfs-monitor-dir" and "inotifywait". (tramp-sh-file-inotifywait-process-filter): Renamed from `tramp-sh-file-notify-process-filter'. (tramp-sh-file-gvfs-monitor-dir-process-filter) (tramp-get-remote-gvfs-monitor-dir): New defuns. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-07-05 02:37:39 +0000 +++ lisp/ChangeLog 2013-07-05 13:34:01 +0000 @@ -1,3 +1,12 @@ +2013-07-05 Michael Albinus + + * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support + both "gvfs-monitor-dir" and "inotifywait". + (tramp-sh-file-inotifywait-process-filter): Renamed from + `tramp-sh-file-notify-process-filter'. + (tramp-sh-file-gvfs-monitor-dir-process-filter) + (tramp-get-remote-gvfs-monitor-dir): New defuns. + 2013-07-05 Leo Liu * autoinsert.el (auto-insert-alist): Default to lexical-binding. === modified file 'lisp/net/tramp-sh.el' --- lisp/net/tramp-sh.el 2013-07-04 09:39:36 +0000 +++ lisp/net/tramp-sh.el 2013-07-05 13:34:01 +0000 @@ -3378,32 +3378,79 @@ ;; Default file name handlers, we don't care. (t (tramp-run-real-handler operation args))))))) -;; We use inotify for implementation. It is more likely to exist than glib. (defun tramp-sh-handle-file-notify-add-watch (file-name flags callback) "Like `file-notify-add-watch' for Tramp files." (setq file-name (expand-file-name file-name)) (with-parsed-tramp-file-name file-name nil (let* ((default-directory (file-name-directory file-name)) - (command (tramp-get-remote-inotifywait v)) - (events - (cond - ((and (memq 'change flags) (memq 'attribute-change flags)) - "create,modify,move,delete,attrib") - ((memq 'change flags) "create,modify,move,delete") - ((memq 'attribute-change flags) "attrib"))) - (p (and command - (start-file-process - "inotifywait" (generate-new-buffer " *inotifywait*") - command "-mq" "-e" events localname)))) + command events filter p) + (cond + ;; gvfs-monitor-dir. + ((setq command (tramp-get-remote-gvfs-monitor-dir v)) + (setq filter 'tramp-sh-file-gvfs-monitor-dir-process-filter + p (start-file-process + "gvfs-monitor-dir" (generate-new-buffer " *gvfs-monitor-dir*") + command localname))) + ;; inotifywait. + ((setq command (tramp-get-remote-inotifywait v)) + (setq filter 'tramp-sh-file-inotifywait-process-filter + events + (cond + ((and (memq 'change flags) (memq 'attribute-change flags)) + "create,modify,move,delete,attrib") + ((memq 'change flags) "create,modify,move,delete") + ((memq 'attribute-change flags) "attrib")) + p (start-file-process + "inotifywait" (generate-new-buffer " *inotifywait*") + command "-mq" "-e" events localname))) + ;; None. + (t (tramp-error + v 'file-notify-error + "No file notification program found on %s" + (file-remote-p file-name)))) ;; Return the process object as watch-descriptor. (if (not (processp p)) (tramp-error - v 'file-notify-error "`inotifywait' not found on remote host") + v 'file-notify-error "`%s' failed to start on remote host" command) (tramp-compat-set-process-query-on-exit-flag p nil) - (set-process-filter p 'tramp-sh-file-notify-process-filter) + (set-process-filter p filter) p)))) -(defun tramp-sh-file-notify-process-filter (proc string) +(defun tramp-sh-file-gvfs-monitor-dir-process-filter (proc string) + "Read output from \"gvfs-monitor-dir\" and add corresponding file-notify events." + (tramp-message proc 6 (format "%S\n%s" proc string)) + (with-current-buffer (process-buffer proc) + (dolist + (line + (split-string string "Directory Monitor Event:[\n\r]+" 'omit-nulls)) + ;; Attribute change is returned in unused wording. + (setq line + (replace-regexp-in-string + "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" line)) + ;; Check, whether there is a problem. + (unless + (string-match + "^Child = \\([^[:blank:]]+\\)[\n\r]+\\(Other = \\([^[:blank:]]+\\)[\n\r]+\\)?Event = \\([^[:blank:]]+\\)[\n\r]+$" line) + (tramp-error proc 'file-notify-error "%s" line)) + + (let* ((remote-prefix (file-remote-p default-directory)) + (object + (list + proc + (intern-soft + (replace-regexp-in-string + "_" "-" (downcase (match-string 4 line)))) + ;; File names are returned as absolute paths. We must + ;; add the remote prefix. + (concat remote-prefix (match-string 1 line)) + (when (match-string 3 line) + (concat remote-prefix (match-string 3 line)))))) + ;; Usually, we would add an Emacs event now. Unfortunately, + ;; `unread-command-events' does not accept several events at + ;; once. Therefore, we apply the callback directly. + (tramp-compat-funcall 'file-notify-callback object))))) + +(defun tramp-sh-file-inotifywait-process-filter (proc string) "Read output from \"inotifywait\" and add corresponding file-notify events." (tramp-message proc 6 (format "%S\n%s" proc string)) (dolist (line (split-string string "[\n\r]+" 'omit-nulls)) @@ -3413,17 +3460,17 @@ "^[^[:blank:]]+[[:blank:]]+\\([^[:blank:]]+\\)+\\([[:blank:]]+\\([^[:blank:]]+\\)\\)?[[:blank:]]*$" line) (tramp-error proc 'file-notify-error "%s" line)) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at once. - ;; Therefore, we apply the callback directly. - (let* ((object - (list - proc - (mapcar - (lambda (x) - (intern-soft (replace-regexp-in-string "_" "-" (downcase x)))) - (split-string (match-string 1 line) "," 'omit-nulls)) - (match-string 3 line)))) + (let ((object + (list + proc + (mapcar + (lambda (x) + (intern-soft (replace-regexp-in-string "_" "-" (downcase x)))) + (split-string (match-string 1 line) "," 'omit-nulls)) + (match-string 3 line)))) + ;; Usually, we would add an Emacs event now. Unfortunately, + ;; `unread-command-events' does not accept several events at + ;; once. Therefore, we apply the callback directly. (tramp-compat-funcall 'file-notify-callback object)))) (defvar file-notify-descriptors) @@ -4923,6 +4970,12 @@ (tramp-message vec 5 "Finding a suitable `trash' command") (tramp-find-executable vec "trash" (tramp-get-remote-path vec)))) +(defun tramp-get-remote-gvfs-monitor-dir (vec) + (with-tramp-connection-property vec "gvfs-monitor-dir" + (tramp-message vec 5 "Finding a suitable `gvfs-monitor-dir' command") + (tramp-find-executable + vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t))) + (defun tramp-get-remote-inotifywait (vec) (with-tramp-connection-property vec "inotifywait" (tramp-message vec 5 "Finding a suitable `inotifywait' command") ------------------------------------------------------------ revno: 113286 committer: Leo Liu branch nick: trunk timestamp: Fri 2013-07-05 10:37:39 +0800 message: * autoinsert.el (auto-insert-alist): Default to lexical-binding. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-07-04 10:25:54 +0000 +++ lisp/ChangeLog 2013-07-05 02:37:39 +0000 @@ -1,3 +1,7 @@ +2013-07-05 Leo Liu + + * autoinsert.el (auto-insert-alist): Default to lexical-binding. + 2013-07-04 YAMAMOTO Mitsuharu * frame.el (display-pixel-height, display-pixel-width) === modified file 'lisp/autoinsert.el' --- lisp/autoinsert.el 2013-01-01 09:11:05 +0000 +++ lisp/autoinsert.el 2013-07-05 02:37:39 +0000 @@ -164,7 +164,10 @@ (("\\.el\\'" . "Emacs Lisp header") "Short description: " - ";;; " (file-name-nondirectory (buffer-file-name)) " --- " str " + ";;; " (file-name-nondirectory (buffer-file-name)) " --- " str + (make-string (max 2 (- 80 (current-column) 27)) ?\s) + "-*- lexical-binding: t; -*-" + " ;; Copyright (C) " (format-time-string "%Y") " " (getenv "ORGANIZATION") | (progn user-full-name) " ------------------------------------------------------------ Use --include-merged or -n0 to see merged revisions.