* filenotify.el @ 2013-06-25 12:02 Michael Albinus 2013-06-25 16:25 ` filenotify.el Rüdiger Sonderfeld ` (2 more replies) 0 siblings, 3 replies; 50+ messages in thread From: Michael Albinus @ 2013-06-25 12:02 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 891 bytes --] Hi, I have written filenotify.el, which is intended as upper layer for gfilenotify.c, inotify.c and w32notify.c. This is a simplified interface, which offers just file change or file attribute change notifications. I believe this is sufficient for the use-cases in Emacs; if more fine granular notifications are needed, one could still use one of the low-level packages. The package is appended, together with needed changes in subr.el and autorevert.el. I've tested it with gfilenotify and inotify; the tests for w32notify I cannot perform as usual. There are still some changes needed, but basic functionality shall be available. Beside further tests and bug fixing, I plan to write ert tests as well as a Tramp file name handler. Documentation is also lacking. But these steps could be applied later, once there is an agreement about the interface. Comments? Best regards, Michael. [-- Attachment #2: filenotify.diff --] [-- Type: text/x-diff, Size: 21329 bytes --] === modified file 'lisp/ChangeLog' *** lisp/ChangeLog 2013-06-25 09:18:09 +0000 --- lisp/ChangeLog 2013-06-25 11:44:00 +0000 *************** *** 1,11 **** 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * lisp/textmodes/bibtex.el (bibtex-generate-url-list): Add support for DOI URLs. 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * lisp/textmodes/bibtex.el (bibtex-mode, bibtex-set-dialect): Update imenu-support when dialect changes. 2013-06-25 Leo Liu <sdl.web@gmail.com> --- 1,23 ---- + 2013-06-25 Michael Albinus <michael.albinus@gmx.de> + + * filenotify.el: New package. + + * autorevert.el (top): Require filenotify.el. + (auto-revert-notify-enabled): Remove. Use `file-notify-support' + instead. + (auto-revert-notify-rm-watch, auto-revert-notify-add-watch) + (auto-revert-notify-handler): Use `file-notify-*' functions. + + * subr.el (file-notify-handle-event): Move function to filenotify.el. + 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * textmodes/bibtex.el (bibtex-generate-url-list): Add support for DOI URLs. 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * textmodes/bibtex.el (bibtex-mode, bibtex-set-dialect): Update imenu-support when dialect changes. 2013-06-25 Leo Liu <sdl.web@gmail.com> === modified file 'lisp/autorevert.el' *** lisp/autorevert.el 2013-06-05 19:57:10 +0000 --- lisp/autorevert.el 2013-06-25 11:41:17 +0000 *************** *** 103,108 **** --- 103,109 ---- (eval-when-compile (require 'cl-lib)) (require 'timer) + (require 'filenotify) ;; Custom Group: ;; *************** *** 270,290 **** :type 'boolean :version "24.4") ! (defconst auto-revert-notify-enabled ! (or (featurep 'gfilenotify) (featurep 'inotify) (featurep 'w32notify)) ! "Non-nil when Emacs has been compiled with file notification support.") ! ! (defcustom auto-revert-use-notify auto-revert-notify-enabled "If non-nil Auto Revert Mode uses file notification functions. This requires Emacs being compiled with file notification ! support (see `auto-revert-notify-enabled'). You should set this ! variable through Custom." :group 'auto-revert :type 'boolean :set (lambda (variable value) ! (set-default variable (and auto-revert-notify-enabled value)) (unless (symbol-value variable) ! (when auto-revert-notify-enabled (dolist (buf (buffer-list)) (with-current-buffer buf (when (symbol-value 'auto-revert-notify-watch-descriptor) --- 271,287 ---- :type 'boolean :version "24.4") ! (defcustom auto-revert-use-notify file-notify-support "If non-nil Auto Revert Mode uses file notification functions. This requires Emacs being compiled with file notification ! support (see `file-notify-support'). You should set this variable ! through Custom." :group 'auto-revert :type 'boolean :set (lambda (variable value) ! (set-default variable (and file-notify-support value)) (unless (symbol-value variable) ! (when file-notify-support (dolist (buf (buffer-list)) (with-current-buffer buf (when (symbol-value 'auto-revert-notify-watch-descriptor) *************** *** 502,513 **** (puthash key value auto-revert-notify-watch-descriptor-hash-list) (remhash key auto-revert-notify-watch-descriptor-hash-list) (ignore-errors ! (funcall ! (cond ! ((fboundp 'gfile-rm-watch) 'gfile-rm-watch) ! ((fboundp 'inotify-rm-watch) 'inotify-rm-watch) ! ((fboundp 'w32notify-rm-watch) 'w32notify-rm-watch)) ! auto-revert-notify-watch-descriptor))))) auto-revert-notify-watch-descriptor-hash-list) (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch)) (setq auto-revert-notify-watch-descriptor nil --- 499,505 ---- (puthash key value auto-revert-notify-watch-descriptor-hash-list) (remhash key auto-revert-notify-watch-descriptor-hash-list) (ignore-errors ! (file-notify-rm-watch auto-revert-notify-watch-descriptor))))) auto-revert-notify-watch-descriptor-hash-list) (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch)) (setq auto-revert-notify-watch-descriptor nil *************** *** 522,621 **** (when (and buffer-file-name auto-revert-use-notify (not auto-revert-notify-watch-descriptor)) ! (let ((func ! (cond ! ((fboundp 'gfile-add-watch) 'gfile-add-watch) ! ((fboundp 'inotify-add-watch) 'inotify-add-watch) ! ((fboundp 'w32notify-add-watch) 'w32notify-add-watch))) ! (aspect ! (cond ! ((fboundp 'gfile-add-watch) '(watch-mounts)) ! ;; `attrib' is needed for file modification time. ! ((fboundp 'inotify-add-watch) '(attrib create modify moved-to)) ! ((fboundp 'w32notify-add-watch) '(size last-write-time)))) ! (file (if (or (fboundp 'gfile-add-watch) (fboundp 'inotify-add-watch)) ! (directory-file-name (expand-file-name default-directory)) ! (buffer-file-name)))) ! (setq auto-revert-notify-watch-descriptor ! (ignore-errors ! (funcall func file aspect 'auto-revert-notify-handler))) ! (if auto-revert-notify-watch-descriptor ! (progn ! (puthash ! auto-revert-notify-watch-descriptor ! (cons (current-buffer) ! (gethash auto-revert-notify-watch-descriptor ! auto-revert-notify-watch-descriptor-hash-list)) ! auto-revert-notify-watch-descriptor-hash-list) ! (add-hook (make-local-variable 'kill-buffer-hook) ! 'auto-revert-notify-rm-watch)) ! ;; Fallback to file checks. ! (set (make-local-variable 'auto-revert-use-notify) nil))))) ! ! (defun auto-revert-notify-event-p (event) ! "Check that event is a file notification event." ! (and (listp event) ! (cond ((featurep 'gfilenotify) ! (and (>= (length event) 3) (stringp (nth 2 event)))) ! ((featurep 'inotify) ! (= (length event) 4)) ! ((featurep 'w32notify) ! (and (= (length event) 3) (stringp (nth 2 event))))))) ! ! (defun auto-revert-notify-event-descriptor (event) ! "Return watch descriptor of file notification event, or nil." ! (and (auto-revert-notify-event-p event) (car event))) ! ! (defun auto-revert-notify-event-action (event) ! "Return action of file notification event, or nil." ! (and (auto-revert-notify-event-p event) (nth 1 event))) ! ! (defun auto-revert-notify-event-file-name (event) ! "Return file name of file notification event, or nil." ! (and (auto-revert-notify-event-p event) ! (cond ((featurep 'gfilenotify) (nth 2 event)) ! ((featurep 'inotify) (nth 3 event)) ! ((featurep 'w32notify) (nth 2 event))))) (defun auto-revert-notify-handler (event) "Handle an EVENT returned from file notification." ! (when (auto-revert-notify-event-p event) ! (let* ((descriptor (auto-revert-notify-event-descriptor event)) ! (action (auto-revert-notify-event-action event)) ! (file (auto-revert-notify-event-file-name event)) ! (buffers (gethash descriptor ! auto-revert-notify-watch-descriptor-hash-list))) ! (ignore-errors ! ;; Check, that event is meant for us. ! ;; TODO: Filter events which stop watching, like `move' or `removed'. ! (cl-assert descriptor) ! (cond ! ((featurep 'gfilenotify) ! (cl-assert (memq action '(attribute-changed changed created deleted ! ;; FIXME: I keep getting this action, so I ! ;; added it here, but I have no idea what ! ;; I'm doing. --Stef ! changes-done-hint)) ! t)) ! ((featurep 'inotify) ! (cl-assert (or (memq 'attrib action) ! (memq 'create action) ! (memq 'modify action) ! (memq 'moved-to action)))) ! ((featurep 'w32notify) (cl-assert (eq 'modified action)))) ! ;; Since we watch a directory, a file name must be returned. ! (cl-assert (stringp file)) ! (dolist (buffer buffers) ! (when (buffer-live-p buffer) ! (with-current-buffer buffer ! (when (and (stringp buffer-file-name) ! (string-equal ! (file-name-nondirectory file) ! (file-name-nondirectory buffer-file-name))) ! ;; Mark buffer modified. ! (setq auto-revert-notify-modified-p t) ! ;; No need to check other buffers. ! (cl-return))))))))) (defun auto-revert-active-p () "Check if auto-revert is active (in current buffer or globally)." --- 514,562 ---- (when (and buffer-file-name auto-revert-use-notify (not auto-revert-notify-watch-descriptor)) ! (setq auto-revert-notify-watch-descriptor ! (ignore-errors ! (file-notify-add-watch ! (directory-file-name (expand-file-name default-directory)) ! '(change attribute-change) 'auto-revert-notify-handler))) ! (if auto-revert-notify-watch-descriptor ! (progn ! (puthash ! auto-revert-notify-watch-descriptor ! (cons (current-buffer) ! (gethash auto-revert-notify-watch-descriptor ! auto-revert-notify-watch-descriptor-hash-list)) ! auto-revert-notify-watch-descriptor-hash-list) ! (add-hook (make-local-variable 'kill-buffer-hook) ! 'auto-revert-notify-rm-watch)) ! ;; Fallback to file checks. ! (set (make-local-variable 'auto-revert-use-notify) nil)))) (defun auto-revert-notify-handler (event) "Handle an EVENT returned from file notification." ! (let* ((descriptor (car event)) ! (action (nth 1 event)) ! (file (nth 2 event)) ! (buffers (gethash descriptor ! auto-revert-notify-watch-descriptor-hash-list))) ! (ignore-errors ! ;; Check, that event is meant for us. ! ;; TODO: Filter events which stop watching, like `move' or `removed'. ! (cl-assert descriptor) ! (cl-assert (memq action '(attribute-changed changed created deleted)) t) ! ;; Since we watch a directory, a file name must be returned. ! (cl-assert (stringp file)) ! (dolist (buffer buffers) ! (when (buffer-live-p buffer) ! (with-current-buffer buffer ! (when (and (stringp buffer-file-name) ! (string-equal ! (file-name-nondirectory file) ! (file-name-nondirectory buffer-file-name))) ! ;; Mark buffer modified. ! (setq auto-revert-notify-modified-p t) ! ;; No need to check other buffers. ! (cl-return)))))))) (defun auto-revert-active-p () "Check if auto-revert is active (in current buffer or globally)." === added file 'lisp/filenotify.el' *** lisp/filenotify.el 1970-01-01 00:00:00 +0000 --- lisp/filenotify.el 2013-06-25 11:36:23 +0000 *************** *** 0 **** --- 1,244 ---- + ;;; filenotify.el --- watch files for changes on disk + + ;; Copyright (C) 2013 Free Software Foundation, Inc. + + ;; Author: Michael Albinus <michael.albinus@gmx.de> + + ;; This file is part of GNU Emacs. + + ;; GNU Emacs is free software: you can redistribute it and/or modify + ;; it under the terms of the GNU General Public License as published by + ;; the Free Software Foundation, either version 3 of the License, or + ;; (at your option) any later version. + + ;; GNU Emacs is distributed in the hope that it will be useful, + ;; but WITHOUT ANY WARRANTY; without even the implied warranty of + ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ;; GNU General Public License for more details. + + ;; You should have received a copy of the GNU General Public License + ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + + ;;; Commentary + + ;; This package is an abstraction layer from the different low-level + ;; file notification packages `gfilenotify', `inotify' and + ;; `w32notify'. + + ;;; Code: + + ;; We check that there is exactly one low-level package. + ;;;###autoload + (defconst file-notify-support + (or (and (featurep 'gfilenotify) + (not (featurep 'inotify)) + (not (featurep 'w32notify))) + (and (not (featurep 'gfilenotify)) + (featurep 'inotify) + (not (featurep 'w32notify))) + (and (not (featurep 'gfilenotify)) + (not (featurep 'inotify)) + (featurep 'w32notify))) + "Non-nil when Emacs has been compiled with file notification support.") + + ;; Shouldn't this be `file-notify-error'? + (defconst filewatch-error nil + "The file notification error symbol") + (put 'filewatch-error 'error-conditions '(filewatch-error file-error error)) + (put 'filewatch-error 'error-message "Filewatch error") + + (defvar file-notify-descriptors (make-hash-table :test 'equal) + "Hash table for registered file notification descriptors. + A key in this hash table is the descriptor as returned from a + `gfilenotify', `inotify' or `w32notify'. The value in the hash + table is the cons cell (FILE . CALLBACK).") + + ;; This function is used by `gfilenotify', `inotify' and `w32notify' events. + ;;;###autoload + (defun file-notify-handle-event (event) + "Handle file system monitoring event. + If EVENT is a filewatch event, call its callback. + Otherwise, signal a `filewatch-error'." + (interactive "e") + (if (and (eq (car event) 'file-notify) + (>= (length event) 3)) + (funcall (nth 2 event) (nth 1 event)) + (signal 'filewatch-error + (cons "Not a valid file-notify event" event)))) + + (defun file-notify-event-file-name (event) + "Return file name of file notification event, or nil." + (cond ((featurep 'gfilenotify) (nth 2 event)) + ((featurep 'inotify) (nth 3 event)) + ((featurep 'w32notify) (nth 2 event)))) + + (defun file-notify-event-file1-name (event) + "Return second file name of file notification event, or nil. + This is available in case a file has been moved." + (cond ((featurep 'gfilenotify) (nth 3 event)) + ((featurep 'inotify) (nth 4 event)) + ((featurep 'w32notify) (nth 3 event)))) + + ;; The callback function used to map between specific flags of the + ;; respective file notifications, and the ones we return. + (defun file-notify-callback (event) + "Handle an EVENT returned from file notification. + EVENT is the same one as in `file-notify-handle-event' except the + car of that event, which is the symbol `file-notify'." + (let ((descriptor (car event)) + (action (nth 1 event)) + (file (file-notify-event-file-name event)) + (file1 (file-notify-event-file1-name event)) + callback tmp) + ;; Check, that event is meant for us. + (unless (setq callback (cdr (gethash descriptor file-notify-descriptors))) + (signal 'filewatch-error (list "Not a valid descriptor" descriptor))) + + ;; Map action. We ignore all events which cannot be mapped. + (setq action + (cond + ((featurep 'gfilenotify) + (cond + ((memq action '(attribute-changed changed created deleted moved)) + action))) + ((featurep 'inotify) + (cond + ((memq 'attrib action) 'attribute-changed) + ((memq 'create action) 'created) + ((memq 'modify action) 'changed) + ((memq 'delete action) 'deleted) + ((memq 'delete-self action) 'deleted) + ((memq 'moved-from action) 'deleted) + ((memq 'moved-to action) 'created) + ((memq 'move-self action) 'deleted))) + ((featurep 'w32notify) + (cond + ((eq 'added action) 'created) + ((eq 'modified action) 'changed) + ((eq 'removed action) 'deleted) + ((eq 'renamed-from action) 'deleted) + ((eq 'renamed-to action) 'created))))) + + ;; Apply callback. + (when (and (stringp file) (eq action 'moved)) + (funcall callback (list descriptor 'deleted file)) + (setq action 'created file file1)) + (when (and (stringp file) action) + (funcall callback (list descriptor action file))))) + + ;; We do not return a `renamed' action, for simplicity. This could be + ;; added later on. + (defun file-notify-add-watch (file flags callback) + "Add a watch for filesystem events pertaining to FILE. + This arranges for filesystem events pertaining to FILE to be reported + to Emacs. Use `file-notify-rm-watch' to cancel the watch. + + The returned value is a descriptor for the added watch. If the + file cannot be watched for some reason, this function signals a + `file-error' error. + + FLAGS is a list of conditions to set what will be watched for. It can + include the following symbols: + + `change' -- watch for file changes + `attribute-change' -- watch for file attributes changes, like + permissions or modification time + + If FILE is a directory, 'change' watches for file creation or + deletion in that directory. + + When any event happens, Emacs will call the CALLBACK function passing + it a single argument EVENT, which is of the form + + (DESCRIPTOR ACTION FILE [FILE1]) + + DESCRIPTOR is the same object as the one returned by this function. + ACTION is the description of the event. It could be any one of the + following: + + `created' -- FILE was created + `deleted' -- FILE was deleted + `changed' -- FILE has changed + `attribute-changed' -- a FILE attribute was changed + + FILE is the name of the file whose event is being reported." + ;; Check arguments. + (unless (stringp file) + (signal 'wrong-type-argument (list file))) + (setq file (expand-file-name file)) + (unless (and (consp flags) + (null (delq 'change (delq 'attribute-change flags)))) + (signal 'wrong-type-argument (list flags))) + (unless (functionp callback) + (signal 'wrong-type-argument (list callback))) + + (let ((handler (find-file-name-handler file 'file-notify-add-watch)) + func fl desc) + (if handler + ;; A file name handler could exist even if there is no local + ;; file notification support. + (setq desc (funcall handler 'file-notify-add-watch file flags callback)) + + ;; Check, whether Emacs has been compiled with file notification support. + (unless file-notify-support + (signal 'filewatch-error '("No file notification package available"))) + + ;; Check, whether this has been registered already. + (maphash + (lambda (key value) + (when (equal (cons file callback) value) (setq desc key))) + file-notify-descriptors) + + (unless desc + ;; Determine local function to be called. + (setq func (cond + ((fboundp 'gfile-add-watch) 'gfile-add-watch) + ((fboundp 'inotify-add-watch) 'inotify-add-watch) + ((fboundp 'w32notify-add-watch) 'w32notify-add-watch))) + + ;; Determine respective flags. + (if (fboundp 'gfile-add-watch) + (setq fl '(watch-mounts)) + (when (memq 'change flags) + (setq + fl + (cond + ((fboundp 'inotify-add-watch) '(create modify move delete)) + ((fboundp 'w32notify-add-watch) '(size last-write-time))))) + (when (memq 'attribute-change flags) + (add-to-list + 'fl + (cond + ((fboundp 'inotify-add-watch) '(attrib)) + ((fboundp 'w32notify-add-watch) '(attributes)))))) + + ;; Call low-level function. + (setq desc (funcall func file fl 'file-notify-callback)))) + + ;; Return descriptor. + (puthash desc (cons file callback) file-notify-descriptors) + desc)) + + (defun file-notify-rm-watch (descriptor) + "Remove an existing watch specified by its DESCRIPTOR. + DESCRIPTOR should be an object returned by `file-notify-add-watch'." + (let ((file (car (gethash descriptor file-notify-descriptors))) + handler) + + (when (stringp file) + (setq handler (find-file-name-handler file 'file-notify-rm-watch)) + (if handler + (funcall handler 'file-notify-rm-watch descriptor) + (funcall + (cond + ((fboundp 'gfile-rm-watch) 'gfile-rm-watch) + ((fboundp 'inotify-rm-watch) 'inotify-rm-watch) + ((fboundp 'w32notify-add-watch) 'w32notify-rm-watch)) + descriptor))) + + (remhash descriptor file-notify-descriptors))) + + ;; The end: + (provide 'filenotify) + + ;;; filenotify.el ends here === modified file 'lisp/subr.el' *** lisp/subr.el 2013-06-20 14:15:42 +0000 --- lisp/subr.el 2013-06-24 07:49:32 +0000 *************** *** 4494,4513 **** nil ,@(cdr (cdr spec))))) \f - ;;;; Support for watching filesystem events. - - (defun file-notify-handle-event (event) - "Handle file system monitoring event. - If EVENT is a filewatch event, call its callback. - Otherwise, signal a `filewatch-error'." - (interactive "e") - (if (and (eq (car event) 'file-notify) - (>= (length event) 3)) - (funcall (nth 2 event) (nth 1 event)) - (signal 'filewatch-error - (cons "Not a valid file-notify event" event)))) - - \f ;;;; Comparing version strings. (defconst version-separator "." --- 4494,4499 ---- ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 12:02 filenotify.el Michael Albinus @ 2013-06-25 16:25 ` Rüdiger Sonderfeld 2013-06-25 19:00 ` filenotify.el Michael Albinus 2013-06-27 12:18 ` filenotify.el (2) Michael Albinus 2013-07-17 13:52 ` filenotify.el Rüdiger Sonderfeld 2 siblings, 1 reply; 50+ messages in thread From: Rüdiger Sonderfeld @ 2013-06-25 16:25 UTC (permalink / raw) To: emacs-devel; +Cc: Michael Albinus Hi, On Tuesday 25 June 2013 14:02:38 Michael Albinus wrote: > I have written filenotify.el, which is intended as upper layer for > gfilenotify.c, inotify.c and w32notify.c. This is a simplified > interface, which offers just file change or file attribute change > notifications. I believe this is sufficient for the use-cases in Emacs; > if more fine granular notifications are needed, one could still use one > of the low-level packages. Thanks for your work so far. I agree for the upper layer portability is most important and not fine granularity. > Beside further tests and bug fixing, I plan to write ert tests as well > as a Tramp file name handler. Documentation is also lacking. But these > steps could be applied later, once there is an agreement about the > interface. Yes, absolutely. There is a very basic test for inotify which could be adopted. > Comments? I have a few comments: + (or (and (featurep 'gfilenotify) + (not (featurep 'inotify)) + (not (featurep 'w32notify))) + (and (not (featurep 'gfilenotify)) + (featurep 'inotify) + (not (featurep 'w32notify))) + (and (not (featurep 'gfilenotify)) + (not (featurep 'inotify)) + (featurep 'w32notify))) Why is the support exclusive? Maybe we could set `file-notify-support' to the name of the low-level feature. This would provide an easy way to identify which one is used. + ;; Shouldn't this be `file-notify-error'? Yes, this would be more consistent in my opinion. + (defun file-notify-event-file1-name (event) ... + ((featurep 'inotify) (nth 4 event)) The event layout for inotify is (WATCH-DESCRIPTOR ASPECTS COOKIE NAME). The new file name will be NAME in the `moved-to' event and it is connected with the COOKIE to the `moved-from' event. + ;; Check, that event is meant for us. + (unless (setq callback (cdr (gethash descriptor file-notify- descriptors))) + (signal 'filewatch-error (list "Not a valid descriptor" descriptor))) I'm not sure if this should be treated as an error. There could be the case that a file event is still in the queue while the watch-descriptor is removed and it will still be delivered. But I just saw that this behaviour was also changed in `file-notify-handle- event' a while ago. I think this needs a bit more discussion. + ((memq 'moved-from action) 'deleted) + ((memq 'moved-to action) 'created) ... + ((eq 'renamed-from action) 'deleted) + ((eq 'renamed-to action) 'created))))) ... + ;; Apply callback. + (when (and (stringp file) (eq action 'moved)) + (funcall callback (list descriptor 'deleted file)) + (setq action 'created file file1)) + (when (and (stringp file) action) + (funcall callback (list descriptor action file))))) I don't think this is very useful because there is no way for the user to connect both events. Inotify provides COOKIE to do this. Maybe we should introduce a moved-from/moved-to event using a cookie instead. This should be easier to implement for all APIs. + ((memq 'move-self action) 'deleted))) Are you sure this is correct? If I remember correctly then inotify sets the file name to the new file name. I'll look into it. Regards Rüdiger ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 16:25 ` filenotify.el Rüdiger Sonderfeld @ 2013-06-25 19:00 ` Michael Albinus 2013-06-25 19:20 ` filenotify.el Eli Zaretskii ` (2 more replies) 0 siblings, 3 replies; 50+ messages in thread From: Michael Albinus @ 2013-06-25 19:00 UTC (permalink / raw) To: Rüdiger Sonderfeld; +Cc: emacs-devel Rüdiger Sonderfeld <ruediger@c-plusplus.de> writes: > Hi, Hi Rüdiger, > I have a few comments: > > + (or (and (featurep 'gfilenotify) > + (not (featurep 'inotify)) > + (not (featurep 'w32notify))) > + (and (not (featurep 'gfilenotify)) > + (featurep 'inotify) > + (not (featurep 'w32notify))) > + (and (not (featurep 'gfilenotify)) > + (not (featurep 'inotify)) > + (featurep 'w32notify))) > > Why is the support exclusive? Just to be sure. The different low-level packages are not fully compatible (event names differ, for example); it would be a nightmare for filenotify.el when the different packages compete under the hood. In general, it could be possible to apply several low-level file notification libraries in parallel. But this wouldn't bring additional features, so we should avoid this. (Out of curiosity, I let compete file monitoring for "/tmp" and "/ssh::/tmp" in parallel. Very funny.) > Maybe we could set `file-notify-support' to the name of the low-level > feature. This would provide an easy way to identify which one is > used. Really? I don't see a serious difference between (featurep 'inotify) and (eq file-notify-support 'inotify) > + ;; Shouldn't this be `file-notify-error'? > > Yes, this would be more consistent in my opinion. If nobody objects, I will change it here as well as in the low-level packages, which use `file-error'. > + (defun file-notify-event-file1-name (event) > ... > + ((featurep 'inotify) (nth 4 event)) > > The event layout for inotify is (WATCH-DESCRIPTOR ASPECTS COOKIE NAME). The > new file name will be NAME in the `moved-to' event and it is connected with > the COOKIE to the `moved-from' event. Just now, this function is used only for gfilenotify, event `moved'. I will remove the other two cases from that function. > + ;; Check, that event is meant for us. > + (unless (setq callback (cdr (gethash descriptor file-notify- > descriptors))) > + (signal 'filewatch-error (list "Not a valid descriptor" descriptor))) > > I'm not sure if this should be treated as an error. There could be the case > that a file event is still in the queue while the watch-descriptor is removed > and it will still be delivered. > > But I just saw that this behaviour was also changed in `file-notify-handle- > event' a while ago. I think this needs a bit more discussion. I believe, that the callback function needs special care from the callee. In `auto-revert-notify-handler', I wrap the sensitive code by `ignore-errors'. For example. But I agree, this might be discussed. > + ((memq 'moved-from action) 'deleted) > + ((memq 'moved-to action) 'created) > ... > + ((eq 'renamed-from action) 'deleted) > + ((eq 'renamed-to action) 'created))))) > ... > + ;; Apply callback. > + (when (and (stringp file) (eq action 'moved)) > + (funcall callback (list descriptor 'deleted file)) > + (setq action 'created file file1)) > + (when (and (stringp file) action) > + (funcall callback (list descriptor action file))))) > > I don't think this is very useful because there is no way for the user to > connect both events. Inotify provides COOKIE to do this. > > Maybe we should introduce a moved-from/moved-to event using a cookie instead. > This should be easier to implement for all APIs. That's also my intention. But Glib's implementation does not implement this for all backends, see the comment in <https://developer.gnome.org/gio/2.36/GFile.html#GFileMonitorFlags-enum>. The w32notify case I couldn't test yet. It is on my todo list; once there is a robust implementation for all low-level packages, we shall add a `renamed' event to be returned. > + ((memq 'move-self action) 'deleted))) > > Are you sure this is correct? If I remember correctly then inotify sets the > file name to the new file name. I'll look into it. I'll check also. > Regards > Rüdiger Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 19:00 ` filenotify.el Michael Albinus @ 2013-06-25 19:20 ` Eli Zaretskii 2013-06-25 19:27 ` filenotify.el Michael Albinus 2013-06-26 0:11 ` filenotify.el Stefan Monnier 2013-06-26 0:45 ` filenotify.el Rüdiger Sonderfeld 2 siblings, 1 reply; 50+ messages in thread From: Eli Zaretskii @ 2013-06-25 19:20 UTC (permalink / raw) To: Michael Albinus; +Cc: ruediger, emacs-devel > From: Michael Albinus <michael.albinus@gmx.de> > Date: Tue, 25 Jun 2013 21:00:43 +0200 > Cc: emacs-devel@gnu.org > > > + ;; Apply callback. > > + (when (and (stringp file) (eq action 'moved)) > > + (funcall callback (list descriptor 'deleted file)) > > + (setq action 'created file file1)) > > + (when (and (stringp file) action) > > + (funcall callback (list descriptor action file))))) > > > > I don't think this is very useful because there is no way for the user to > > connect both events. Inotify provides COOKIE to do this. > > > > Maybe we should introduce a moved-from/moved-to event using a cookie instead. > > This should be easier to implement for all APIs. > > That's also my intention. But Glib's implementation does not implement > this for all backends, see the comment in > <https://developer.gnome.org/gio/2.36/GFile.html#GFileMonitorFlags-enum>. > > The w32notify case I couldn't test yet. w32notify produces 2 events for a file that was renamed: a 'renamed-from' event, followed by a 'renamed-to' event. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 19:20 ` filenotify.el Eli Zaretskii @ 2013-06-25 19:27 ` Michael Albinus 2013-06-25 20:14 ` filenotify.el Eli Zaretskii 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-06-25 19:27 UTC (permalink / raw) To: Eli Zaretskii; +Cc: ruediger, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: > w32notify produces 2 events for a file that was renamed: a > 'renamed-from' event, followed by a 'renamed-to' event. Is there a guarantee, that `renamed-to' will always follow `renamed-from'? No other event in between? How long shall we wait, until we give up, and show 'renamed-from' as `deleted'? Events could be lost. Btw, the same question arises for inotify. But here we have the cookie, which gives a better correlation. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 19:27 ` filenotify.el Michael Albinus @ 2013-06-25 20:14 ` Eli Zaretskii 2013-06-26 6:06 ` filenotify.el Michael Albinus 0 siblings, 1 reply; 50+ messages in thread From: Eli Zaretskii @ 2013-06-25 20:14 UTC (permalink / raw) To: Michael Albinus; +Cc: ruediger, emacs-devel > From: Michael Albinus <michael.albinus@gmx.de> > Cc: ruediger@c-plusplus.de, emacs-devel@gnu.org > Date: Tue, 25 Jun 2013 21:27:57 +0200 > > Eli Zaretskii <eliz@gnu.org> writes: > > > w32notify produces 2 events for a file that was renamed: a > > 'renamed-from' event, followed by a 'renamed-to' event. > > Is there a guarantee, that `renamed-to' will always follow > `renamed-from'? No other event in between? > > How long shall we wait, until we give up, and show 'renamed-from' as > `deleted'? Events could be lost. I'd say, if the very next event is not renamed-to, stop waiting. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 20:14 ` filenotify.el Eli Zaretskii @ 2013-06-26 6:06 ` Michael Albinus 0 siblings, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-06-26 6:06 UTC (permalink / raw) To: Eli Zaretskii; +Cc: ruediger, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> How long shall we wait, until we give up, and show 'renamed-from' as >> `deleted'? Events could be lost. > > I'd say, if the very next event is not renamed-to, stop waiting. Thanks, I'll implement it this way. If there is a pending `renamed-from' event, and the next event is not `renamed-to', I'll fire the pending event as `removed' before handling the incoming event. Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 19:00 ` filenotify.el Michael Albinus 2013-06-25 19:20 ` filenotify.el Eli Zaretskii @ 2013-06-26 0:11 ` Stefan Monnier 2013-06-26 6:21 ` filenotify.el Michael Albinus 2013-06-26 0:45 ` filenotify.el Rüdiger Sonderfeld 2 siblings, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-06-26 0:11 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > Just to be sure. The different low-level packages are not fully > compatible (event names differ, for example); it would be a nightmare > for filenotify.el when the different packages compete under the hood. Why would they compete? In the unlikely case that both gfilenotify and inotify are provided, can't the code just use one of the two without being impacted by the other? If not, why not? Can we fix it so as to avoid such conflicts? > In general, it could be possible to apply several low-level file > notification libraries in parallel. But this wouldn't bring additional > features, so we should avoid this. Agreed, but the better option is to make sure they don't conflict with each other, and then make filenotify.el choose one of the available ones "arbitrarily". We may also want to tweak configure to avod building Emacs with support for multiple file notification systems, but if we assume a future with FFI, then multiple notification systems may occur dynamically and there isn't any good reason to really disallow it. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 0:11 ` filenotify.el Stefan Monnier @ 2013-06-26 6:21 ` Michael Albinus 2013-06-26 13:04 ` filenotify.el Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-06-26 6:21 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Just to be sure. The different low-level packages are not fully >> compatible (event names differ, for example); it would be a nightmare >> for filenotify.el when the different packages compete under the hood. > > Why would they compete? In the unlikely case that both gfilenotify and > inotify are provided, can't the code just use one of the two without > being impacted by the other? If not, why not? Can we fix it so as to > avoid such conflicts? [...] > Agreed, but the better option is to make sure they don't conflict with > each other, and then make filenotify.el choose one of the available ones > "arbitrarily". Well, filenotify.el shall decide for one of the available low-level packages, and use it. I'll change accordingly. However, any Lisp package could still decide to activate "the other" low-level file notification package if linked to Emacs. In this case, we must ensure that the incoming file-notify events can be distinguished. Such an event looks like (DESCRIPTOR ACTION FILE). Different low-level packages must use unique DESCRIPTORs then. As of today, this is not guaranteed; both gfilenotify and inotify use integers for example. There's no urgency for this; as of today Emacs' configure decides for one and only one package. And in Tramp I use already descriptors which are unique for Tramp (it's the internal Tramp vector for the file to be monitored). > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 6:21 ` filenotify.el Michael Albinus @ 2013-06-26 13:04 ` Stefan Monnier 2013-06-26 14:15 ` filenotify.el Michael Albinus 0 siblings, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-06-26 13:04 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > However, any Lisp package could still decide to activate "the other" > low-level file notification package if linked to Emacs. So what? > In this case, we must ensure that the incoming file-notify events can > be distinguished. Where? In the C code or in filenotify.el? AFAICT, at the Elisp level, a callback is only called for a given "watcher" (which is even more specific than a "notification library"), so I see no reason why a callback setup with inotify-add-watch should be called by gfilenotify, for example. > Such an event looks like (DESCRIPTOR ACTION FILE). Different low-level > packages must use unique DESCRIPTORs then. Just use (inotify DESCRIPTOR ACTION FILE) instead, if that's really needed. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 13:04 ` filenotify.el Stefan Monnier @ 2013-06-26 14:15 ` Michael Albinus 2013-06-26 14:28 ` filenotify.el Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-06-26 14:15 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> In this case, we must ensure that the incoming file-notify events can >> be distinguished. > > Where? In the C code or in filenotify.el? AFAICT, at the Elisp level, > a callback is only called for a given "watcher" (which is even more > specific than a "notification library"), so I see no reason why > a callback setup with inotify-add-watch should be called by gfilenotify, > for example. Imagine there are two registered watchers: (gfile-add-watch "/tmp" flags1 'callback1) (inotify-add-watch "/tmp" flags2 'callback2) Both return the same descriptor, let's say 1. What would you call, when there is an incoming event (1 flag "123") for the file "/tmp/123"? Would you apply callback1 or callback2? You don't know whether the event comes from gfilenotify or inotify. Maybe one could distinguish wrt the returned flag, but I wouldn't bet that's always unique. >> Such an event looks like (DESCRIPTOR ACTION FILE). Different low-level >> packages must use unique DESCRIPTORs then. > > Just use (inotify DESCRIPTOR ACTION FILE) instead, if that's really needed. I would make the descriptor a cons cell '(inotify . number), but it is the same idea. Again, for Tramp I use already a vector as descriptor. The only promise we have given is, that descriptors returned by *-add-watch functions can be distinguished via `equal'. No need to change it today, because there are no two packages linked in parallel yet. But this might be needed in the future. > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 14:15 ` filenotify.el Michael Albinus @ 2013-06-26 14:28 ` Stefan Monnier 2013-06-26 14:37 ` filenotify.el Michael Albinus 2013-06-26 15:57 ` filenotify.el Eli Zaretskii 0 siblings, 2 replies; 50+ messages in thread From: Stefan Monnier @ 2013-06-26 14:28 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > Imagine there are two registered watchers: > (gfile-add-watch "/tmp" flags1 'callback1) > (inotify-add-watch "/tmp" flags2 'callback2) > Both return the same descriptor, let's say 1. What would you call, when > there is an incoming event (1 flag "123") for the file "/tmp/123"? Who's "you"? IIUC it's the C code, so if the C code calls inotify's callback when receiving gfile's event it's a bug in the C code that needs fixing regardless of filenotify.el. >>> Such an event looks like (DESCRIPTOR ACTION FILE). Different low-level >>> packages must use unique DESCRIPTORs then. >> Just use (inotify DESCRIPTOR ACTION FILE) instead, if that's really needed. > I would make the descriptor a cons cell '(inotify . number), but it is > the same idea. I don't see any need to make any change to the Elisp visible behavior. > Again, for Tramp I use already a vector as descriptor. > The only promise we have given is, that descriptors returned by > *-add-watch functions can be distinguished via `equal'. Also that a callback is only called for those events on which it was added. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 14:28 ` filenotify.el Stefan Monnier @ 2013-06-26 14:37 ` Michael Albinus 2013-06-26 15:57 ` filenotify.el Eli Zaretskii 1 sibling, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-06-26 14:37 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Imagine there are two registered watchers: >> (gfile-add-watch "/tmp" flags1 'callback1) >> (inotify-add-watch "/tmp" flags2 'callback2) >> Both return the same descriptor, let's say 1. What would you call, when >> there is an incoming event (1 flag "123") for the file "/tmp/123"? > > Who's "you"? IIUC it's the C code, so if the C code calls inotify's > callback when receiving gfile's event it's a bug in the C code that > needs fixing regardless of filenotify.el. "you" is `file-notify-handle-event'. It is in subr.el, I will move it to filenotify.el. It does not know of gfilenotify, inotify or w32notify. > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 14:28 ` filenotify.el Stefan Monnier 2013-06-26 14:37 ` filenotify.el Michael Albinus @ 2013-06-26 15:57 ` Eli Zaretskii 2013-06-26 19:59 ` filenotify.el Stefan Monnier 1 sibling, 1 reply; 50+ messages in thread From: Eli Zaretskii @ 2013-06-26 15:57 UTC (permalink / raw) To: Stefan Monnier; +Cc: ruediger, michael.albinus, emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Date: Wed, 26 Jun 2013 10:28:24 -0400 > Cc: Rüdiger Sonderfeld <ruediger@c-plusplus.de>, > emacs-devel@gnu.org > > > Imagine there are two registered watchers: > > (gfile-add-watch "/tmp" flags1 'callback1) > > (inotify-add-watch "/tmp" flags2 'callback2) > > Both return the same descriptor, let's say 1. What would you call, when > > there is an incoming event (1 flag "123") for the file "/tmp/123"? > > Who's "you"? IIUC it's the C code No. C code just pushes an event onto the event queue. The rest is done in Lisp. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 15:57 ` filenotify.el Eli Zaretskii @ 2013-06-26 19:59 ` Stefan Monnier 2013-06-26 20:28 ` filenotify.el Michael Albinus 0 siblings, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-06-26 19:59 UTC (permalink / raw) To: Eli Zaretskii; +Cc: ruediger, michael.albinus, emacs-devel >> > Imagine there are two registered watchers: >> > (gfile-add-watch "/tmp" flags1 'callback1) >> > (inotify-add-watch "/tmp" flags2 'callback2) >> > Both return the same descriptor, let's say 1. What would you call, when >> > there is an incoming event (1 flag "123") for the file "/tmp/123"? >> Who's "you"? IIUC it's the C code > No. C code just pushes an event onto the event queue. The rest is > done in Lisp. Then the event should have an `inotify', `w32notify' or `gfile' tag. Of course, that could be included in the "cookie" (which really should be a new object type either in Lisp_Misc or in Lisp_Vectorlike). Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 19:59 ` filenotify.el Stefan Monnier @ 2013-06-26 20:28 ` Michael Albinus 0 siblings, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-06-26 20:28 UTC (permalink / raw) To: Stefan Monnier; +Cc: ruediger, Eli Zaretskii, emacs-devel Stefan Monnier <monnier@IRO.UMontreal.CA> writes: > Then the event should have an `inotify', `w32notify' or `gfile' tag. > Of course, that could be included in the "cookie" (which really should > be a new object type either in Lisp_Misc or in Lisp_Vectorlike). We have had that in the beginning ... it has been changed, in order to apply the same event handler for all the notification events. Which tag would you give an event when it is pushed by Tramp? `remote'? Honestly, I don't believe it is worth the trouble just now, since we haven't a problem yet. We could think about when it is necessary. Changing the event name wouldn't break anything; it is used internally only in the different *notify.{c,el} packages. And putting the tag into the descriptor, as I have proposed, would even not require a change in the event name. The descriptors must just be unique, that's all. > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 19:00 ` filenotify.el Michael Albinus 2013-06-25 19:20 ` filenotify.el Eli Zaretskii 2013-06-26 0:11 ` filenotify.el Stefan Monnier @ 2013-06-26 0:45 ` Rüdiger Sonderfeld 2013-06-26 6:40 ` filenotify.el Michael Albinus 2 siblings, 1 reply; 50+ messages in thread From: Rüdiger Sonderfeld @ 2013-06-26 0:45 UTC (permalink / raw) To: emacs-devel; +Cc: Michael Albinus One minor nitpick I forgot: You should use two hyphens for functions which are not meant to be used by the user. I guess this should also include `file- notify--handle-event'. It seems those symbols * file-notify-callback * file-notify-descriptors * file-notify-event-file-name * file-notify-event-file1-name * file-notify-callback should not be directly used by the user. On Tuesday 25 June 2013 21:00:43 you wrote: > Just to be sure. The different low-level packages are not fully > compatible (event names differ, for example); it would be a nightmare > for filenotify.el when the different packages compete under the hood. > > In general, it could be possible to apply several low-level file > notification libraries in parallel. But this wouldn't bring additional > features, so we should avoid this. > > (Out of curiosity, I let compete file monitoring for "/tmp" and > "/ssh::/tmp" in parallel. Very funny.) I agree with Stefan here. I don't see a reason why Emacs couldn't be compiled with several filenotify APIs. Both inotify and gfilenotify are available on the same system. filenotify.el should of course only pick one. But it shouldn't really be affected if there are more available. > > Maybe we could set `file-notify-support' to the name of the low-level > > feature. This would provide an easy way to identify which one is > > used. > > Really? I don't see a serious difference between (featurep 'inotify) and > (eq file-notify-support 'inotify) This would of course only make sense if the support isn't exclusive. > I believe, that the callback function needs special care from the > callee. In `auto-revert-notify-handler', I wrap the sensitive code by > `ignore-errors'. For example. But this error couldn't be handled by `ignore-errors' because it happens before the callback is called. Or am I misunderstanding you? Regards Rüdiger ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-26 0:45 ` filenotify.el Rüdiger Sonderfeld @ 2013-06-26 6:40 ` Michael Albinus 2013-06-26 7:50 ` About `<prefix>--' (was Re: filenotify.el) Stephen Berman 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-06-26 6:40 UTC (permalink / raw) To: Rüdiger Sonderfeld; +Cc: emacs-devel Rüdiger Sonderfeld <ruediger@c-plusplus.de> writes: > One minor nitpick I forgot: You should use two hyphens for functions which > are not meant to be used by the user. Ahh. This is a rather new coding style in Emacs; it didn't even find its way into the Lisp Refefence Manual yet :-) But it's useful; I'll apply. > I guess this should also include `file-notify--handle-event'. Don't know. I'm not decided yet whether to use this function also in Tramp. >> Really? I don't see a serious difference between (featurep 'inotify) and >> (eq file-notify-support 'inotify) > > This would of course only make sense if the support isn't exclusive. OK, so I set it to the used package symbol. But it must be documented clearly, that this is applied for *local* file systems only; Tramp will use a different implementation very likely. Later, when there are several low-level file notification packages linked to Emacs in parallel, we could change `file-notify-support' into a defcustom. The user could decide which of the packages to use. Maybe we shall give it another name for that purpose. >> I believe, that the callback function needs special care from the >> callee. In `auto-revert-notify-handler', I wrap the sensitive code by >> `ignore-errors'. For example. > > But this error couldn't be handled by `ignore-errors' because it happens > before the callback is called. Or am I misunderstanding you? Where shall this happen? In `file-notify-handle-event'? This function does not depend on a registered file watcher. > Regards > Rüdiger Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* About `<prefix>--' (was Re: filenotify.el) 2013-06-26 6:40 ` filenotify.el Michael Albinus @ 2013-06-26 7:50 ` Stephen Berman 2013-06-26 13:06 ` Stefan Monnier 2013-06-27 23:19 ` Josh 0 siblings, 2 replies; 50+ messages in thread From: Stephen Berman @ 2013-06-26 7:50 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel On Wed, 26 Jun 2013 08:40:11 +0200 Michael Albinus <michael.albinus@gmx.de> wrote: > Rüdiger Sonderfeld <ruediger@c-plusplus.de> writes: > >> One minor nitpick I forgot: You should use two hyphens for functions which >> are not meant to be used by the user. > > Ahh. This is a rather new coding style in Emacs; it didn't even find > its way into the Lisp Refefence Manual yet :-) Actually, it did, but just barely, in (elisp)Coding Conventions: Separate the prefix from the rest of the name with a hyphen, `-'. Use two hyphens if the symbol is not meant to be used by other packages. This practice helps avoid name conflicts, since all global variables in Emacs Lisp share the same name space, and all functions share another name space I have two problems with this. First, the "Use two hyphens" sentence shouldn't come between the other two, since "This practice" in the following sentence only refers to using the prefix, not two hyphens. Second, "not meant to be used by other packages" is too vague for me to feel confident about how to apply it. For example, in the new version of todo-mode.el I recently committed to the trunk, there aren't really any symbols, including those naming commands and user options, meant to be used by other packages, since it's not a general purpose library. On the other hand, it does contain some internal functions and variables of a rather general character, needed to implement parts of the UI, which I included because Emacs doesn't have them (e.g. a powerset function), and these certainly could be used by other packages, but more likely they would be reimplemented using the package prefix. So it's not clear to me where the dividing line is. It could be taken to be everything except commands and user options, as Rüdiger seems to imply (unless he meant "the user" is a package, not a human). But it's clearly not been used so restrictively in Emacs to date (indeed, mpc.el even contains a command `mpc--faster'). So I would find it helpful if there were more specific guidelines about how to apply this convention. Steve Berman ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-26 7:50 ` About `<prefix>--' (was Re: filenotify.el) Stephen Berman @ 2013-06-26 13:06 ` Stefan Monnier 2013-06-26 22:36 ` Stephen Berman 2013-06-27 23:19 ` Josh 1 sibling, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-06-26 13:06 UTC (permalink / raw) To: Stephen Berman; +Cc: Rüdiger Sonderfeld, Michael Albinus, emacs-devel > I have two problems with this. First, the "Use two hyphens" sentence > shouldn't come between the other two, since "This practice" in the > following sentence only refers to using the prefix, not two hyphens. Good point. > Second, "not meant to be used by other packages" is too vague for me to > feel confident about how to apply it. For example, in the new version It means that something defined with "--" can completely change (or disappear) from one release to the other. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-26 13:06 ` Stefan Monnier @ 2013-06-26 22:36 ` Stephen Berman 2013-06-27 1:39 ` Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Stephen Berman @ 2013-06-26 22:36 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, Michael Albinus, emacs-devel On Wed, 26 Jun 2013 09:06:52 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> Second, "not meant to be used by other packages" is too vague for me to >> feel confident about how to apply it. For example, in the new version > > It means that something defined with "--" can completely change (or > disappear) from one release to the other. Can I borrow your crystal ball before the next release? Steve Berman ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-26 22:36 ` Stephen Berman @ 2013-06-27 1:39 ` Stefan Monnier 0 siblings, 0 replies; 50+ messages in thread From: Stefan Monnier @ 2013-06-27 1:39 UTC (permalink / raw) To: Stephen Berman; +Cc: Rüdiger Sonderfeld, Michael Albinus, emacs-devel >>> Second, "not meant to be used by other packages" is too vague for me to >>> feel confident about how to apply it. For example, in the new version >> It means that something defined with "--" can completely change (or >> disappear) from one release to the other. > Can I borrow your crystal ball before the next release? Sure, I'll put it on GNU ELPA, so everyone can benefit, Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-26 7:50 ` About `<prefix>--' (was Re: filenotify.el) Stephen Berman 2013-06-26 13:06 ` Stefan Monnier @ 2013-06-27 23:19 ` Josh 2013-06-28 3:00 ` Xue Fuqiao 2013-06-28 21:59 ` Richard Stallman 1 sibling, 2 replies; 50+ messages in thread From: Josh @ 2013-06-27 23:19 UTC (permalink / raw) To: Stephen Berman; +Cc: Rüdiger Sonderfeld, Michael Albinus, emacs-devel On Wed, Jun 26, 2013 at 12:50 AM, Stephen Berman <stephen.berman@gmx.net> wrote: > [...] On > the other hand, it does contain some internal functions and variables of > a rather general character, needed to implement parts of the UI, which I > included because Emacs doesn't have them (e.g. a powerset function), and > these certainly could be used by other packages, but more likely they > would be reimplemented using the package prefix. Coincidentally enough, I needed a power set function just yesterday. After fruitlessly grepping for one on my system I ended up writing my own. I wish I had procrastinated a bit longer so I could have used yours :) It would be great if more of these generally useful functions were "promoted" from the libraries where they originated into the core of Emacs, stripped of package prefixes and properly documented in the Emacs or Elisp info manuals in order to make them more discoverable for use elsewhere. Doubtless many wheels have been reinvented after failed searches for functionality that already ships with Emacs. For example, I have implemented and later stumbled across existing implementations of anaphora (later found in lisp/ibuf-macs.el) and a recursive directory-files function (later found in lisp/gnus/gnus-util.el). I'd expect discoverability to worsen as libraries continue to move out of grep's reach in the core to GNU ELPA, Marmalade, Github, etc., which in turn would result in greater duplication of effort as well as proliferation of similar but subtly incompatible implementations of general-purpose functions. Users' interest in a richer set of elisp building blocks is evident from the existence and popularity of libraries such as Magnar Sveen's dash[0] ("a modern list library for emacs") and s[1] ("the long lost Emacs string manipulation library"). IMO it would be a worthwhile goal to move toward shipping canonical implementations of these building blocks with Emacs. What do others think? Josh [0] https://github.com/magnars/dash.el [1] https://github.com/magnars/s.el ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-27 23:19 ` Josh @ 2013-06-28 3:00 ` Xue Fuqiao 2013-06-28 22:54 ` Stefan Monnier 2013-06-28 21:59 ` Richard Stallman 1 sibling, 1 reply; 50+ messages in thread From: Xue Fuqiao @ 2013-06-28 3:00 UTC (permalink / raw) To: Josh; +Cc: Rüdiger Sonderfeld, Stephen Berman, Michael Albinus, emacs-devel On Fri, Jun 28, 2013 at 7:19 AM, Josh <josh@foxtail.org> wrote: > It would be great if more of these generally useful functions were > "promoted" from the libraries where they originated into the core of > Emacs, stripped of package prefixes and properly documented in the > Emacs or Elisp info manuals in order to make them more discoverable > for use elsewhere. Doubtless many wheels have been reinvented after > failed searches for functionality that already ships with Emacs. > Users' interest in a richer set of elisp building blocks is evident > from the existence and popularity of libraries such as Magnar Sveen's > dash[0] ("a modern list library for emacs") and s[1] ("the long lost > Emacs string manipulation library"). IMO it would be a worthwhile > goal to move toward shipping canonical implementations of these > building blocks with Emacs. What do others think? Agreed. XOR is also an example. Some generally useful features have been added to core Emacs Lisp recently (e.g., generalized variables), and more ones are expected, I think. -- Best regards, Xue Fuqiao. http://www.gnu.org/software/emacs/ ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-28 3:00 ` Xue Fuqiao @ 2013-06-28 22:54 ` Stefan Monnier 2013-06-28 23:50 ` Xue Fuqiao 0 siblings, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-06-28 22:54 UTC (permalink / raw) To: Xue Fuqiao Cc: Rüdiger Sonderfeld, Josh, Stephen Berman, Michael Albinus, emacs-devel > Agreed. XOR is also an example. Some generally useful features have > been added to core Emacs Lisp recently (e.g., generalized variables), Notice that these are language features, whereas powerset is in a different category of "occasionally useful library function". We sadly don't have a good place to put such generic functions. Maybe we could create a new "set" library of set functions (union, intersection, difference, powerset, membership, negation, ...). Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-28 22:54 ` Stefan Monnier @ 2013-06-28 23:50 ` Xue Fuqiao 2013-06-29 2:06 ` Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Xue Fuqiao @ 2013-06-28 23:50 UTC (permalink / raw) To: Stefan Monnier Cc: Rüdiger Sonderfeld, Josh, Stephen Berman, Michael Albinus, emacs-devel On Sat, Jun 29, 2013 at 6:54 AM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> Agreed. XOR is also an example. Some generally useful features have >> been added to core Emacs Lisp recently (e.g., generalized variables), > > Notice that these are language features, whereas powerset is in > a different category of "occasionally useful library function". Yes, if you subdivide. I organized them by one category: generally useful features (which can be used by many other libraries). > We sadly don't have a good place to put such generic functions. > Maybe we could create a new "set" library of set functions > (union, intersection, difference, powerset, membership, negation, ...). And some other suggestions (I did not think too much): * A list library (to provide something subr.el and cl-lib missed) * A string manipulation library * A math library (maybe Calc is enough?) * A hash library (implements a common interface to different secure hash algorithms.) * A time access and conversion library * A logging facility library * The long lost concurrency and FFI libraries * An I18N library [OT] And some not-so-general suggestions: * Interface to the DBM database * Interface to the SQLite database (like this one: http://www.emacswiki.org/emacs/sqlite.el) * A CSV file reading and writing library (maybe csv-mode from GNU ELPA is a good choice) * A JSON encoder and decoder * Access to the POSIX locale database and functionality. -- Best regards, Xue Fuqiao. http://www.gnu.org/software/emacs/ ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-28 23:50 ` Xue Fuqiao @ 2013-06-29 2:06 ` Stefan Monnier 0 siblings, 0 replies; 50+ messages in thread From: Stefan Monnier @ 2013-06-29 2:06 UTC (permalink / raw) To: Xue Fuqiao Cc: Rüdiger Sonderfeld, Josh, Stephen Berman, Michael Albinus, emacs-devel > * A list library (to provide something subr.el and cl-lib missed) We could have a list library (with "list-" prefix). I'm not sure if it'll be worth the trouble now that we have cl-lib (before, with cl.el most of its list functions were out of reach, because cl.el could not be used at run-time, but this problem doesn't plague cl-lib). > * A string manipulation library > * A math library (maybe Calc is enough?) > * A hash library (implements a common interface to different secure hash > algorithms.) > * A time access and conversion library > * A logging facility library > * The long lost concurrency and FFI libraries > * An I18N library All sounds fine. For some of them, we already have a file for them (e.g. time-date.el). The main problem is for functions which would most naturally end up in subr.el: since subr.el is preloaded, we'd rather put there only functions which are very likely to be used. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-27 23:19 ` Josh 2013-06-28 3:00 ` Xue Fuqiao @ 2013-06-28 21:59 ` Richard Stallman 2013-06-30 18:50 ` Josh 1 sibling, 1 reply; 50+ messages in thread From: Richard Stallman @ 2013-06-28 21:59 UTC (permalink / raw) To: Josh; +Cc: ruediger, stephen.berman, michael.albinus, emacs-devel [ To any NSA and FBI agents reading my email: please consider [ whether defending the US Constitution against all enemies, [ foreign or domestic, requires you to follow Snowden's example. It would be great if more of these generally useful functions were "promoted" from the libraries where they originated into the core of Emacs, stripped of package prefixes and properly documented in the Emacs or Elisp info manuals in order to make them more discoverable for use elsewhere. The downside of this is that it would require documenting all these functions in the Emacs Lisp Reference Manual, which is already unwieldy. It might be better for people to reinvent these as needed. Or put them in a separate category with the prefix `aux-' and document them in a different manual. -- Dr Richard Stallman President, Free Software Foundation 51 Franklin St Boston MA 02110 USA www.fsf.org www.gnu.org Skype: No way! That's nonfree (freedom-denying) software. Use Ekiga or an ordinary phone call. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: About `<prefix>--' (was Re: filenotify.el) 2013-06-28 21:59 ` Richard Stallman @ 2013-06-30 18:50 ` Josh 0 siblings, 0 replies; 50+ messages in thread From: Josh @ 2013-06-30 18:50 UTC (permalink / raw) To: rms; +Cc: Rüdiger Sonderfeld, Stephen Berman, Michael Albinus, emacs-devel On Fri, Jun 28, 2013 at 2:59 PM, Richard Stallman <rms@gnu.org> wrote: > The downside of this is that it would require documenting all these > functions in the Emacs Lisp Reference Manual, which is already > unwieldy. What does "unwieldy" mean in the context of an easily searchable and navigable hypertext resource like the elisp manual? > It might be better for people to reinvent these as needed. > Or put them in a separate category with the prefix `aux-' and document > them in a different manual. People are already reinventing such functions in large numbers today, but I believe this is frequently not "as needed" but because we wrongly believe it doesn't exist yet after failing to find evidence to the contrary in the documentation and/or source code where it would logically appear if it did. It seems to me that prefixing some set of functions (which ones?) with "aux-" and documenting them in a separate manual could only exacerbate this problem. ^ permalink raw reply [flat|nested] 50+ messages in thread
* filenotify.el (2) 2013-06-25 12:02 filenotify.el Michael Albinus 2013-06-25 16:25 ` filenotify.el Rüdiger Sonderfeld @ 2013-06-27 12:18 ` Michael Albinus 2013-07-04 9:54 ` Michael Albinus 2013-07-17 13:52 ` filenotify.el Rüdiger Sonderfeld 2 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-06-27 12:18 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 418 bytes --] Hi, Enclosed is the updated version of the patch. I have incorporated the comments, and I have also modified inotify.c and gfilenotify.c in order to use `file-notify-error'. This shall also be changed in w32notify.c; since I cannot test the build on Windows I haven't done it yet. I have also started to write test/automated/file-notify-tests.el, but this is far from being presentable yet. Best regards, Michael. [-- Attachment #2: filenotify.diff --] [-- Type: text/x-diff, Size: 33775 bytes --] === modified file 'lisp/ChangeLog' *** lisp/ChangeLog 2013-06-27 09:26:54 +0000 --- lisp/ChangeLog 2013-06-27 12:03:14 +0000 *************** *** 1,3 **** --- 1,15 ---- + 2013-06-27 Michael Albinus <michael.albinus@gmx.de> + + * filenotify.el: New package. + + * autorevert.el (top): Require filenotify.el. + (auto-revert-notify-enabled): Remove. Use `file-notify-support' + instead. + (auto-revert-notify-rm-watch, auto-revert-notify-add-watch) + (auto-revert-notify-handler): Use `file-notify-*' functions. + + * subr.el (file-notify-handle-event): Move function to filenotify.el. + 2013-06-27 Dmitry Gutov <dgutov@yandex.ru> * emacs-lisp/package-x.el (package-upload-buffer-internal): Adapt *************** *** 153,164 **** 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * lisp/textmodes/bibtex.el (bibtex-generate-url-list): Add support for DOI URLs. 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * lisp/textmodes/bibtex.el (bibtex-mode, bibtex-set-dialect): Update imenu-support when dialect changes. 2013-06-25 Leo Liu <sdl.web@gmail.com> --- 165,176 ---- 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * textmodes/bibtex.el (bibtex-generate-url-list): Add support for DOI URLs. 2013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> ! * textmodes/bibtex.el (bibtex-mode, bibtex-set-dialect): Update imenu-support when dialect changes. 2013-06-25 Leo Liu <sdl.web@gmail.com> === modified file 'lisp/autorevert.el' *** lisp/autorevert.el 2013-06-05 19:57:10 +0000 --- lisp/autorevert.el 2013-06-27 09:00:44 +0000 *************** *** 103,108 **** --- 103,109 ---- (eval-when-compile (require 'cl-lib)) (require 'timer) + (require 'filenotify) ;; Custom Group: ;; *************** *** 270,290 **** :type 'boolean :version "24.4") ! (defconst auto-revert-notify-enabled ! (or (featurep 'gfilenotify) (featurep 'inotify) (featurep 'w32notify)) ! "Non-nil when Emacs has been compiled with file notification support.") ! ! (defcustom auto-revert-use-notify auto-revert-notify-enabled "If non-nil Auto Revert Mode uses file notification functions. This requires Emacs being compiled with file notification ! support (see `auto-revert-notify-enabled'). You should set this ! variable through Custom." :group 'auto-revert :type 'boolean :set (lambda (variable value) ! (set-default variable (and auto-revert-notify-enabled value)) (unless (symbol-value variable) ! (when auto-revert-notify-enabled (dolist (buf (buffer-list)) (with-current-buffer buf (when (symbol-value 'auto-revert-notify-watch-descriptor) --- 271,287 ---- :type 'boolean :version "24.4") ! (defcustom auto-revert-use-notify (and file-notify-support t) "If non-nil Auto Revert Mode uses file notification functions. This requires Emacs being compiled with file notification ! support (see `file-notify-support'). You should set this variable ! through Custom." :group 'auto-revert :type 'boolean :set (lambda (variable value) ! (set-default variable (and file-notify-support value)) (unless (symbol-value variable) ! (when file-notify-support (dolist (buf (buffer-list)) (with-current-buffer buf (when (symbol-value 'auto-revert-notify-watch-descriptor) *************** *** 502,513 **** (puthash key value auto-revert-notify-watch-descriptor-hash-list) (remhash key auto-revert-notify-watch-descriptor-hash-list) (ignore-errors ! (funcall ! (cond ! ((fboundp 'gfile-rm-watch) 'gfile-rm-watch) ! ((fboundp 'inotify-rm-watch) 'inotify-rm-watch) ! ((fboundp 'w32notify-rm-watch) 'w32notify-rm-watch)) ! auto-revert-notify-watch-descriptor))))) auto-revert-notify-watch-descriptor-hash-list) (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch)) (setq auto-revert-notify-watch-descriptor nil --- 499,505 ---- (puthash key value auto-revert-notify-watch-descriptor-hash-list) (remhash key auto-revert-notify-watch-descriptor-hash-list) (ignore-errors ! (file-notify-rm-watch auto-revert-notify-watch-descriptor))))) auto-revert-notify-watch-descriptor-hash-list) (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch)) (setq auto-revert-notify-watch-descriptor nil *************** *** 522,621 **** (when (and buffer-file-name auto-revert-use-notify (not auto-revert-notify-watch-descriptor)) ! (let ((func ! (cond ! ((fboundp 'gfile-add-watch) 'gfile-add-watch) ! ((fboundp 'inotify-add-watch) 'inotify-add-watch) ! ((fboundp 'w32notify-add-watch) 'w32notify-add-watch))) ! (aspect ! (cond ! ((fboundp 'gfile-add-watch) '(watch-mounts)) ! ;; `attrib' is needed for file modification time. ! ((fboundp 'inotify-add-watch) '(attrib create modify moved-to)) ! ((fboundp 'w32notify-add-watch) '(size last-write-time)))) ! (file (if (or (fboundp 'gfile-add-watch) (fboundp 'inotify-add-watch)) ! (directory-file-name (expand-file-name default-directory)) ! (buffer-file-name)))) ! (setq auto-revert-notify-watch-descriptor ! (ignore-errors ! (funcall func file aspect 'auto-revert-notify-handler))) ! (if auto-revert-notify-watch-descriptor ! (progn ! (puthash ! auto-revert-notify-watch-descriptor ! (cons (current-buffer) ! (gethash auto-revert-notify-watch-descriptor ! auto-revert-notify-watch-descriptor-hash-list)) ! auto-revert-notify-watch-descriptor-hash-list) ! (add-hook (make-local-variable 'kill-buffer-hook) ! 'auto-revert-notify-rm-watch)) ! ;; Fallback to file checks. ! (set (make-local-variable 'auto-revert-use-notify) nil))))) ! ! (defun auto-revert-notify-event-p (event) ! "Check that event is a file notification event." ! (and (listp event) ! (cond ((featurep 'gfilenotify) ! (and (>= (length event) 3) (stringp (nth 2 event)))) ! ((featurep 'inotify) ! (= (length event) 4)) ! ((featurep 'w32notify) ! (and (= (length event) 3) (stringp (nth 2 event))))))) ! ! (defun auto-revert-notify-event-descriptor (event) ! "Return watch descriptor of file notification event, or nil." ! (and (auto-revert-notify-event-p event) (car event))) ! ! (defun auto-revert-notify-event-action (event) ! "Return action of file notification event, or nil." ! (and (auto-revert-notify-event-p event) (nth 1 event))) ! ! (defun auto-revert-notify-event-file-name (event) ! "Return file name of file notification event, or nil." ! (and (auto-revert-notify-event-p event) ! (cond ((featurep 'gfilenotify) (nth 2 event)) ! ((featurep 'inotify) (nth 3 event)) ! ((featurep 'w32notify) (nth 2 event))))) (defun auto-revert-notify-handler (event) "Handle an EVENT returned from file notification." ! (when (auto-revert-notify-event-p event) ! (let* ((descriptor (auto-revert-notify-event-descriptor event)) ! (action (auto-revert-notify-event-action event)) ! (file (auto-revert-notify-event-file-name event)) (buffers (gethash descriptor auto-revert-notify-watch-descriptor-hash-list))) ! (ignore-errors ! ;; Check, that event is meant for us. ! ;; TODO: Filter events which stop watching, like `move' or `removed'. ! (cl-assert descriptor) ! (cond ! ((featurep 'gfilenotify) ! (cl-assert (memq action '(attribute-changed changed created deleted ! ;; FIXME: I keep getting this action, so I ! ;; added it here, but I have no idea what ! ;; I'm doing. --Stef ! changes-done-hint)) ! t)) ! ((featurep 'inotify) ! (cl-assert (or (memq 'attrib action) ! (memq 'create action) ! (memq 'modify action) ! (memq 'moved-to action)))) ! ((featurep 'w32notify) (cl-assert (eq 'modified action)))) ! ;; Since we watch a directory, a file name must be returned. ! (cl-assert (stringp file)) ! (dolist (buffer buffers) ! (when (buffer-live-p buffer) ! (with-current-buffer buffer ! (when (and (stringp buffer-file-name) ! (string-equal ! (file-name-nondirectory file) ! (file-name-nondirectory buffer-file-name))) ! ;; Mark buffer modified. ! (setq auto-revert-notify-modified-p t) ! ;; No need to check other buffers. ! (cl-return))))))))) (defun auto-revert-active-p () "Check if auto-revert is active (in current buffer or globally)." --- 514,571 ---- (when (and buffer-file-name auto-revert-use-notify (not auto-revert-notify-watch-descriptor)) ! (setq auto-revert-notify-watch-descriptor ! (ignore-errors ! (file-notify-add-watch ! (directory-file-name (expand-file-name default-directory)) ! '(change attribute-change) 'auto-revert-notify-handler))) ! (if auto-revert-notify-watch-descriptor ! (progn ! (puthash ! auto-revert-notify-watch-descriptor ! (cons (current-buffer) ! (gethash auto-revert-notify-watch-descriptor ! auto-revert-notify-watch-descriptor-hash-list)) ! auto-revert-notify-watch-descriptor-hash-list) ! (add-hook (make-local-variable 'kill-buffer-hook) ! 'auto-revert-notify-rm-watch)) ! ;; Fallback to file checks. ! (set (make-local-variable 'auto-revert-use-notify) nil)))) (defun auto-revert-notify-handler (event) "Handle an EVENT returned from file notification." ! (ignore-errors ! (let* ((descriptor (car event)) ! (action (nth 1 event)) ! (file (nth 2 event)) ! (file1 (nth 3 event)) ;; Target of `renamed'. (buffers (gethash descriptor auto-revert-notify-watch-descriptor-hash-list))) ! ;; Check, that event is meant for us. ! (cl-assert descriptor) ! ;; We do not handle `deleted', because nothing has to be refreshed. ! (cl-assert (memq action '(attribute-changed changed created renamed)) t) ! ;; Since we watch a directory, a file name must be returned. ! (cl-assert (stringp file)) ! (when (eq action 'renamed) (cl-assert (stringp file1))) ! ;; Loop over all buffers, in order to find the intended one. ! (dolist (buffer buffers) ! (when (buffer-live-p buffer) ! (with-current-buffer buffer ! (when (and (stringp buffer-file-name) ! (or ! (and (memq action '(attribute-changed changed created)) ! (string-equal ! (file-name-nondirectory file) ! (file-name-nondirectory buffer-file-name))) ! (and (eq action 'renamed) ! (string-equal ! (file-name-nondirectory file1) ! (file-name-nondirectory buffer-file-name))))) ! ;; Mark buffer modified. ! (setq auto-revert-notify-modified-p t) ! ;; No need to check other buffers. ! (cl-return)))))))) (defun auto-revert-active-p () "Check if auto-revert is active (in current buffer or globally)." === added file 'lisp/filenotify.el' *** lisp/filenotify.el 1970-01-01 00:00:00 +0000 --- lisp/filenotify.el 2013-06-27 06:49:24 +0000 *************** *** 0 **** --- 1,292 ---- + ;;; filenotify.el --- watch files for changes on disk + + ;; Copyright (C) 2013 Free Software Foundation, Inc. + + ;; Author: Michael Albinus <michael.albinus@gmx.de> + + ;; This file is part of GNU Emacs. + + ;; GNU Emacs is free software: you can redistribute it and/or modify + ;; it under the terms of the GNU General Public License as published by + ;; the Free Software Foundation, either version 3 of the License, or + ;; (at your option) any later version. + + ;; GNU Emacs is distributed in the hope that it will be useful, + ;; but WITHOUT ANY WARRANTY; without even the implied warranty of + ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ;; GNU General Public License for more details. + + ;; You should have received a copy of the GNU General Public License + ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + + ;;; Commentary + + ;; This package is an abstraction layer from the different low-level + ;; file notification packages `gfilenotify', `inotify' and + ;; `w32notify'. + + ;;; Code: + + ;;;###autoload + (defconst file-notify-support + (cond + ((featurep 'gfilenotify) 'gfilenotify) + ((featurep 'inotify) 'inotify) + ((featurep 'w32notify) 'w32notify)) + "Non-nil when Emacs has been compiled with file notification support. + The value is the name of the low-level file notification package + to be used for local file systems. Remote file notifications + could use another implementation.") + + (defvar file-notify-descriptors (make-hash-table :test 'equal) + "Hash table for registered file notification descriptors. + A key in this hash table is the descriptor as returned from a + `gfilenotify', `inotify' or `w32notify'. The value in the hash + table is the cons cell (FILE . CALLBACK).") + + ;; This function is used by `gfilenotify', `inotify' and `w32notify' events. + ;;;###autoload + (defun file-notify-handle-event (event) + "Handle file system monitoring event. + If EVENT is a filewatch event, call its callback. + Otherwise, signal a `file-notify-error'." + (interactive "e") + (if (and (eq (car event) 'file-notify) + (>= (length event) 3)) + (funcall (nth 2 event) (nth 1 event)) + (signal 'file-notify-error + (cons "Not a valid file-notify event" event)))) + + (defvar file-notify--pending-event nil + "Pending file notification event for a future `renamed' action. + This is a list (DESCRIPTOR ACTION COOKIE FILE), or nil. ACTION + is either `moved-from' or `renamed-from'.") + + (defun file-notify--event-file-name (event) + "Return file name of file notification event, or nil." + (cond ((eq file-notify-support 'gfilenotify) (nth 2 event)) + ((eq file-notify-support 'inotify) (nth 3 event)) + ((eq file-notify-support 'w32notify) (nth 2 event)))) + + ;; Only `gfilenotify' could return two file names. + (defun file-notify--event-file1-name (event) + "Return second file name of file notification event, or nil. + This is available in case a file has been moved." + (and (eq file-notify-support 'gfilenotify) (nth 3 event))) + + ;; Cookies are offered by `inotify' only. + (defun file-notify--event-cookie (event) + "Return cookie of file notification event, or nil. + This is available in case a file has been moved." + (and (eq file-notify-support 'inotify) (nth 2 event))) + + ;; The callback function used to map between specific flags of the + ;; respective file notifications, and the ones we return. + (defun file-notify-callback (event) + "Handle an EVENT returned from file notification. + EVENT is the same one as in `file-notify-handle-event' except the + car of that event, which is the symbol `file-notify'." + (let ((descriptor (car event)) + (actions (nth 1 event)) + (file (file-notify--event-file-name event)) + file1 cookie callback tmp) + ;; Check, that event is meant for us. + (unless (setq callback (cdr (gethash descriptor file-notify-descriptors))) + (signal 'file-notify-error (list "Not a valid descriptor" descriptor))) + + ;; Make actions a list. + (unless (consp actions) (setq actions (cons actions nil))) + + ;; Loop over actions. In fact, more than one action happens only + ;; for `inotify'. + (dolist (action actions) + + ;; Send pending event, if it doesn't match. + (when (and file-notify--pending-event + ;; The cookie doesn't match. + (not (eq (nth 2 file-notify--pending-event) + (file-notify--event-cookie event))) + (or + ;; inotify. + (and (eq (nth 1 file-notify--pending-event) 'moved-from) + (not (eq action 'moved-to))) + ;; w32notify. + (and (eq (nth 1 file-notify--pending-event) 'renamed-from) + (not (eq action 'renamed-to))))) + (funcall callback + (list (nth 0 file-notify--pending-event) + 'deleted (nth 3 file-notify--pending-event))) + (setq file-notify--pending-event nil)) + + ;; Map action. We ignore all events which cannot be mapped. + (setq action + (cond + ;; gfilenotify. + ((memq action '(attribute-changed changed created deleted)) action) + ((eq action 'moved) + (setq file1 (file-notify--event-file1-name event)) + 'renamed) + + ;; inotify. + ((eq action 'attrib) 'attribute-changed) + ((eq action 'create) 'created) + ((eq action 'modify) 'changed) + ((memq action '(delete 'delete-self move-self)) 'deleted) + ;; Make the event pending. + ((eq action 'moved-from) + (setq file-notify--pending-event + (list descriptor action + (file-notify--event-cookie event) file)) + nil) + ;; Look for pending event. + ((eq action 'moved-to) + (if (null file-notify--pending-event) + 'created + (setq file1 file + file (nth 3 file-notify--pending-event) + file-notify--pending-event nil) + 'renamed)) + + ;; w32notify. + ((eq action 'added) 'created) + ((eq action 'modified) 'changed) + ((eq action 'removed) 'deleted) + ;; Make the event pending. + ((eq 'renamed-from action) + (setq file-notify--pending-event + (list descriptor action nil file)) + nil) + ;; Look for pending event. + ((eq 'renamed-to action) + (if (null file-notify--pending-event) + 'created + (setq file1 file + file (nth 3 file-notify--pending-event) + file-notify--pending-event nil) + 'renamed)))) + + ;; Apply callback. + (when action + (if file1 + (funcall callback (list descriptor action file file1)) + (funcall callback (list descriptor action file))))))) + + (defun file-notify-add-watch (file flags callback) + "Add a watch for filesystem events pertaining to FILE. + This arranges for filesystem events pertaining to FILE to be reported + to Emacs. Use `file-notify-rm-watch' to cancel the watch. + + The returned value is a descriptor for the added watch. If the + file cannot be watched for some reason, this function signals a + `file-error' error. + + FLAGS is a list of conditions to set what will be watched for. It can + include the following symbols: + + `change' -- watch for file changes + `attribute-change' -- watch for file attributes changes, like + permissions or modification time + + If FILE is a directory, 'change' watches for file creation or + deletion in that directory. + + When any event happens, Emacs will call the CALLBACK function passing + it a single argument EVENT, which is of the form + + (DESCRIPTOR ACTION FILE [FILE1]) + + DESCRIPTOR is the same object as the one returned by this function. + ACTION is the description of the event. It could be any one of the + following: + + `created' -- FILE was created + `deleted' -- FILE was deleted + `changed' -- FILE has changed + `renamed' -- FILE has been renamed to FILE1 + `attribute-changed' -- a FILE attribute was changed + + FILE is the name of the file whose event is being reported." + ;; Check arguments. + (unless (stringp file) + (signal 'wrong-type-argument (list file))) + (setq file (expand-file-name file)) + (unless (and (consp flags) + (null (delq 'change (delq 'attribute-change (copy-tree flags))))) + (signal 'wrong-type-argument (list flags))) + (unless (functionp callback) + (signal 'wrong-type-argument (list callback))) + + (let ((handler (find-file-name-handler file 'file-notify-add-watch)) + func fl desc) + + ;; Check, whether this has been registered already. + (maphash + (lambda (key value) + (when (equal (cons file callback) value) (setq desc key))) + file-notify-descriptors) + + (unless desc + (if handler + ;; A file name handler could exist even if there is no local + ;; file notification support. + (setq desc + (funcall handler 'file-notify-add-watch file flags callback)) + + ;; Check, whether Emacs has been compiled with file + ;; notification support. + (unless file-notify-support + (signal 'file-notify-error + '("No file notification package available"))) + + ;; Determine local function to be called. + (setq func (cond + ((eq file-notify-support 'gfilenotify) 'gfile-add-watch) + ((eq file-notify-support 'inotify) 'inotify-add-watch) + ((eq file-notify-support 'w32notify) 'w32notify-add-watch))) + + ;; Determine respective flags. + (if (eq file-notify-support 'gfilenotify) + (setq fl '(watch-mounts send-moved)) + (when (memq 'change flags) + (setq + fl + (cond + ((eq file-notify-support 'inotify) '(create modify move delete)) + ((eq file-notify-support 'w32notify) '(size last-write-time))))) + (when (memq 'attribute-change flags) + (add-to-list + 'fl + (cond + ((eq file-notify-support 'inotify) 'attrib) + ((eq file-notify-support 'w32notify) 'attributes))))) + + ;; Call low-level function. + (setq desc (funcall func file fl 'file-notify-callback)))) + + ;; Return descriptor. + (puthash desc (cons file callback) file-notify-descriptors) + desc)) + + (defun file-notify-rm-watch (descriptor) + "Remove an existing watch specified by its DESCRIPTOR. + DESCRIPTOR should be an object returned by `file-notify-add-watch'." + (let ((file (car (gethash descriptor file-notify-descriptors))) + handler) + + (when (stringp file) + (setq handler (find-file-name-handler file 'file-notify-rm-watch)) + (if handler + (funcall handler 'file-notify-rm-watch descriptor) + (funcall + (cond + ((eq file-notify-support 'gfilenotify) 'gfile-rm-watch) + ((eq file-notify-support 'inotify) 'inotify-rm-watch) + ((eq file-notify-support 'w32notify) 'w32notify-rm-watch)) + descriptor))) + + (remhash descriptor file-notify-descriptors))) + + ;; The end: + (provide 'filenotify) + + ;;; filenotify.el ends here === modified file 'lisp/subr.el' *** lisp/subr.el 2013-06-20 14:15:42 +0000 --- lisp/subr.el 2013-06-24 07:49:32 +0000 *************** *** 4494,4513 **** nil ,@(cdr (cdr spec))))) \f - ;;;; Support for watching filesystem events. - - (defun file-notify-handle-event (event) - "Handle file system monitoring event. - If EVENT is a filewatch event, call its callback. - Otherwise, signal a `filewatch-error'." - (interactive "e") - (if (and (eq (car event) 'file-notify) - (>= (length event) 3)) - (funcall (nth 2 event) (nth 1 event)) - (signal 'filewatch-error - (cons "Not a valid file-notify event" event)))) - - \f ;;;; Comparing version strings. (defconst version-separator "." --- 4494,4499 ---- === modified file 'src/ChangeLog' *** src/ChangeLog 2013-06-24 00:31:31 +0000 --- src/ChangeLog 2013-06-27 11:56:19 +0000 *************** *** 1,3 **** --- 1,13 ---- + 2013-06-27 Michael Albinus <michael.albinus@gmx.de> + + * fileio.c (Qfile_notify_error): New error symbol. + + * gfilenotify.c (Fgfile_add_watch, Fgfile_rm_watch): + * inotify.c (inotify_callback, symbol_to_inotifymask) + (Finotify_add_watch, Finotify_rm_watch): Use it. + + * lisp.h (Qfile_notify_error): Declare. + 2013-06-23 Paul Eggert <eggert@cs.ucla.edu> A more-conservative workaround for Cygwin SIGCHLD issues (Bug#14569). === modified file 'src/fileio.c' *** src/fileio.c 2013-06-18 07:42:37 +0000 --- src/fileio.c 2013-06-26 07:56:12 +0000 *************** *** 148,154 **** #ifdef WINDOWSNT #endif ! Lisp_Object Qfile_error; static Lisp_Object Qfile_already_exists, Qfile_date_error; static Lisp_Object Qexcl; Lisp_Object Qfile_name_history; --- 148,154 ---- #ifdef WINDOWSNT #endif ! Lisp_Object Qfile_error, Qfile_notify_error; static Lisp_Object Qfile_already_exists, Qfile_date_error; static Lisp_Object Qexcl; Lisp_Object Qfile_name_history; *************** *** 5887,5892 **** --- 5887,5893 ---- DEFSYM (Qfile_error, "file-error"); DEFSYM (Qfile_already_exists, "file-already-exists"); DEFSYM (Qfile_date_error, "file-date-error"); + DEFSYM (Qfile_notify_error, "file-notify-error"); DEFSYM (Qexcl, "excl"); DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system, *************** *** 5925,5930 **** --- 5926,5936 ---- Fput (Qfile_date_error, Qerror_message, build_pure_c_string ("Cannot set file date")); + Fput (Qfile_notify_error, Qerror_conditions, + Fpurecopy (list3 (Qfile_notify_error, Qfile_error, Qerror))); + Fput (Qfile_notify_error, Qerror_message, + build_pure_c_string ("File notification error")); + DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially. If a file name matches REGEXP, all I/O on that file is done by calling === modified file 'src/gfilenotify.c' *** src/gfilenotify.c 2013-06-06 07:04:35 +0000 --- src/gfilenotify.c 2013-06-27 11:47:42 +0000 *************** *** 132,146 **** to Emacs. Use `gfile-rm-watch' to cancel the watch. Value is a descriptor for the added watch. If the file cannot be ! watched for some reason, this function signals a `file-error' error. FLAGS is a list of conditions to set what will be watched for. It can include the following symbols: 'watch-mounts' -- watch for mount events 'send-moved' -- pair 'deleted' and 'created' events caused by file ! renames (moves) and send a single 'event-moved' ! event instead When any event happens, Emacs will call the CALLBACK function passing it a single argument EVENT, which is of the form --- 132,145 ---- to Emacs. Use `gfile-rm-watch' to cancel the watch. Value is a descriptor for the added watch. If the file cannot be ! watched for some reason, this function signals a `file-notify-error' error. FLAGS is a list of conditions to set what will be watched for. It can include the following symbols: 'watch-mounts' -- watch for mount events 'send-moved' -- pair 'deleted' and 'created' events caused by file ! renames and send a single 'renamed' event instead When any event happens, Emacs will call the CALLBACK function passing it a single argument EVENT, which is of the form *************** *** 193,199 **** /* Enable watch. */ monitor = g_file_monitor (gfile, gflags, NULL, NULL); if (! monitor) ! xsignal2 (Qfile_error, build_string ("Cannot watch file"), file); /* On all known glib platforms, converting MONITOR directly to a Lisp_Object value results is a Lisp integer, which is safe. This --- 192,198 ---- /* Enable watch. */ monitor = g_file_monitor (gfile, gflags, NULL, NULL); if (! monitor) ! xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file); /* On all known glib platforms, converting MONITOR directly to a Lisp_Object value results is a Lisp integer, which is safe. This *************** *** 202,208 **** if (! INTEGERP (watch_descriptor)) { g_object_unref (monitor); ! xsignal2 (Qfile_error, build_string ("Unsupported file watcher"), file); } g_signal_connect (monitor, "changed", --- 201,208 ---- if (! INTEGERP (watch_descriptor)) { g_object_unref (monitor); ! xsignal2 (Qfile_notify_error, build_string ("Unsupported file watcher"), ! file); } g_signal_connect (monitor, "changed", *************** *** 226,239 **** Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list); if (! CONSP (watch_object)) ! xsignal2 (Qfile_error, build_string ("Not a watch descriptor"), watch_descriptor); eassert (INTEGERP (watch_descriptor)); int_monitor = XLI (watch_descriptor); monitor = (GFileMonitor *) int_monitor; if (!g_file_monitor_cancel (monitor)) ! xsignal2 (Qfile_error, build_string ("Could not rm watch"), watch_descriptor); /* Remove watch descriptor from watch list. */ --- 226,239 ---- Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list); if (! CONSP (watch_object)) ! xsignal2 (Qfile_notify_error, build_string ("Not a watch descriptor"), watch_descriptor); eassert (INTEGERP (watch_descriptor)); int_monitor = XLI (watch_descriptor); monitor = (GFileMonitor *) int_monitor; if (!g_file_monitor_cancel (monitor)) ! xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"), watch_descriptor); /* Remove watch descriptor from watch list. */ === modified file 'src/inotify.c' *** src/inotify.c 2013-01-02 16:30:50 +0000 --- src/inotify.c 2013-06-27 08:42:14 +0000 *************** *** 158,172 **** to_read = 0; if (ioctl (fd, FIONREAD, &to_read) == -1) ! report_file_error ("Error while trying to retrieve file system events", ! Qnil); buffer = xmalloc (to_read); n = read (fd, buffer, to_read); if (n < 0) { xfree (buffer); ! report_file_error ("Error while trying to read file system events", ! Qnil); } EVENT_INIT (event); --- 158,174 ---- to_read = 0; if (ioctl (fd, FIONREAD, &to_read) == -1) ! xsignal1 ! (Qfile_notify_error, ! build_string ("Error while trying to retrieve file system events")); buffer = xmalloc (to_read); n = read (fd, buffer, to_read); if (n < 0) { xfree (buffer); ! xsignal1 ! (Qfile_notify_error, ! build_string ("Error while trying to read file system events")); } EVENT_INIT (event); *************** *** 242,248 **** else if (EQ (symb, Qt) || EQ (symb, Qall_events)) return IN_ALL_EVENTS; else ! signal_error ("Unknown aspect", symb); } static uint32_t --- 244,250 ---- else if (EQ (symb, Qt) || EQ (symb, Qall_events)) return IN_ALL_EVENTS; else ! xsignal2 (Qfile_notify_error, build_string ("Unknown aspect"), symb); } static uint32_t *************** *** 335,342 **** if (inotifyfd == -1) { inotifyfd = uninitialized; ! report_file_error ("File watching feature (inotify) is not available", ! Qnil); } watch_list = Qnil; add_read_fd (inotifyfd, &inotify_callback, NULL); --- 337,345 ---- if (inotifyfd == -1) { inotifyfd = uninitialized; ! xsignal1 ! (Qfile_notify_error, ! build_string ("File watching feature (inotify) is not available")); } watch_list = Qnil; add_read_fd (inotifyfd, &inotify_callback, NULL); *************** *** 346,352 **** encoded_file_name = ENCODE_FILE (file_name); watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask); if (watchdesc == -1) ! report_file_error ("Could not add watch for file", Fcons (file_name, Qnil)); watch_descriptor = make_watch_descriptor (watchdesc); --- 349,356 ---- encoded_file_name = ENCODE_FILE (file_name); watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask); if (watchdesc == -1) ! xsignal2 (Qfile_notify_error, ! build_string ("Could not add watch for file"), file_name); watch_descriptor = make_watch_descriptor (watchdesc); *************** *** 375,382 **** int wd = XINT (watch_descriptor); if (inotify_rm_watch (inotifyfd, wd) == -1) ! report_file_error ("Could not rm watch", Fcons (watch_descriptor, ! Qnil)); /* Remove watch descriptor from watch list. */ watch_object = Fassoc (watch_descriptor, watch_list); --- 379,386 ---- int wd = XINT (watch_descriptor); if (inotify_rm_watch (inotifyfd, wd) == -1) ! xsignal2 (Qfile_notify_error, ! build_string ("Could not rm watch"), watch_descriptor); /* Remove watch descriptor from watch list. */ watch_object = Fassoc (watch_descriptor, watch_list); === modified file 'src/lisp.h' *** src/lisp.h 2013-06-21 20:11:44 +0000 --- src/lisp.h 2013-06-26 07:41:17 +0000 *************** *** 3799,3804 **** --- 3799,3805 ---- /* Defined in fileio.c. */ extern Lisp_Object Qfile_error; + extern Lisp_Object Qfile_notify_error; extern Lisp_Object Qfile_exists_p; extern Lisp_Object Qfile_directory_p; extern Lisp_Object Qinsert_file_contents; ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el (2) 2013-06-27 12:18 ` filenotify.el (2) Michael Albinus @ 2013-07-04 9:54 ` Michael Albinus 0 siblings, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-04 9:54 UTC (permalink / raw) To: emacs-devel Michael Albinus <michael.albinus@gmx.de> writes: Hi, > Enclosed is the updated version of the patch. Installed in the trunk. Also file name handlers for Tramp, and a first version of a related ert test file. Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-06-25 12:02 filenotify.el Michael Albinus 2013-06-25 16:25 ` filenotify.el Rüdiger Sonderfeld 2013-06-27 12:18 ` filenotify.el (2) Michael Albinus @ 2013-07-17 13:52 ` Rüdiger Sonderfeld 2013-07-17 14:54 ` filenotify.el Michael Albinus 2 siblings, 1 reply; 50+ messages in thread From: Rüdiger Sonderfeld @ 2013-07-17 13:52 UTC (permalink / raw) To: emacs-devel; +Cc: Michael Albinus Hello, I've written a new "Auto Update" module for magit using the new API: https://github.com/magit/magit/pull/721 Best regards, Rüdiger On Tuesday 25 June 2013 14:02:38 Michael Albinus wrote: > Hi, > > I have written filenotify.el, which is intended as upper layer for > gfilenotify.c, inotify.c and w32notify.c. This is a simplified > interface, which offers just file change or file attribute change > notifications. I believe this is sufficient for the use-cases in Emacs; > if more fine granular notifications are needed, one could still use one > of the low-level packages. > > The package is appended, together with needed changes in subr.el and > autorevert.el. I've tested it with gfilenotify and inotify; the tests > for w32notify I cannot perform as usual. There are still some changes > needed, but basic functionality shall be available. > > Beside further tests and bug fixing, I plan to write ert tests as well > as a Tramp file name handler. Documentation is also lacking. But these > steps could be applied later, once there is an agreement about the > interface. > > Comments? > > Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-17 13:52 ` filenotify.el Rüdiger Sonderfeld @ 2013-07-17 14:54 ` Michael Albinus 2013-07-17 16:21 ` filenotify.el Rüdiger Sonderfeld 2013-07-22 18:17 ` filenotify.el Davis Herring 0 siblings, 2 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-17 14:54 UTC (permalink / raw) To: Rüdiger Sonderfeld; +Cc: emacs-devel Rüdiger Sonderfeld <ruediger@c-plusplus.de> writes: > Hello, Hi Rüdiger, > I've written a new "Auto Update" module for magit using the new API: > https://github.com/magit/magit/pull/721 Nice :-) One remark: the following code is not sufficient: (defun magit-filenotify-start () "Start watching for changes to the source tree using filenotify. This can only be called from a magit status buffer." (unless file-notify-support (error "Support for `file-notify' required.")) ... There could be support even if `file-notify-support' is nil. This variable reflects only, whether a respective library has been linked to Emacs, working for local files. `file-notify' could run for remote files, even if it is not supported locally. Maybe we shall spend a new function (defun file-notify-supported-p (file) "Returns non-nil if filesystem pertaining to FILE could be watched." ... Comments? > Best regards, > Rüdiger Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-17 14:54 ` filenotify.el Michael Albinus @ 2013-07-17 16:21 ` Rüdiger Sonderfeld 2013-07-18 10:10 ` filenotify.el Michael Albinus 2013-07-22 18:17 ` filenotify.el Davis Herring 1 sibling, 1 reply; 50+ messages in thread From: Rüdiger Sonderfeld @ 2013-07-17 16:21 UTC (permalink / raw) To: Michael Albinus; +Cc: emacs-devel Hi Michael, On Wednesday 17 July 2013 16:54:34 Michael Albinus wrote: > Maybe we shall spend a new function > > (defun file-notify-supported-p (file) > "Returns non-nil if filesystem pertaining to FILE could be watched." > ... > > Comments? Sounds like a good idea. Regards Rüdiger ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-17 16:21 ` filenotify.el Rüdiger Sonderfeld @ 2013-07-18 10:10 ` Michael Albinus 0 siblings, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-18 10:10 UTC (permalink / raw) To: Rüdiger Sonderfeld; +Cc: emacs-devel Rüdiger Sonderfeld <ruediger@c-plusplus.de> writes: > Hi Michael, Hi Rüdiger, >> Maybe we shall spend a new function >> >> (defun file-notify-supported-p (file) >> "Returns non-nil if filesystem pertaining to FILE could be watched." >> ... >> >> Comments? > > Sounds like a good idea. Committed to trunk as r113447. > Regards > Rüdiger Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-17 14:54 ` filenotify.el Michael Albinus 2013-07-17 16:21 ` filenotify.el Rüdiger Sonderfeld @ 2013-07-22 18:17 ` Davis Herring 2013-07-22 18:28 ` filenotify.el Michael Albinus 1 sibling, 1 reply; 50+ messages in thread From: Davis Herring @ 2013-07-22 18:17 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > (defun magit-filenotify-start () > "Start watching for changes to the source tree using filenotify. > This can only be called from a magit status buffer." > (unless file-notify-support > (error "Support for `file-notify' required.")) > ... > > There could be support even if `file-notify-support' is nil. This > variable reflects only, whether a respective library has been linked to > Emacs, working for local files. `file-notify' could run for remote > files, even if it is not supported locally. > > Maybe we shall spend a new function > > (defun file-notify-supported-p (file) > "Returns non-nil if filesystem pertaining to FILE could be watched." > ... > > Comments? Why not just let the error from the underlying notification request appear? (This is the usual bit about "don't call stat(2) before open(2); just deal with failures from the latter".) Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-22 18:17 ` filenotify.el Davis Herring @ 2013-07-22 18:28 ` Michael Albinus 2013-07-22 19:00 ` filenotify.el Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-07-22 18:28 UTC (permalink / raw) To: Davis Herring; +Cc: Rüdiger Sonderfeld, emacs-devel Davis Herring <herring@lanl.gov> writes: > Why not just let the error from the underlying notification request > appear? (This is the usual bit about "don't call stat(2) before > open(2); just deal with failures from the latter".) That would be possible, yes. But I hope to improve file-notify-supported-p, that it could also return a correct answer in case the underlying library does not support the filesystem in question. Example: mounted directories. (file-notify-supported-p "/mnt/dir") will return t when either gfilenotify or inotify are linked to Emacs. And file-notify-add-watch won't fail in either case. But likely, in the inotify case you won't see events, because it does not support mounted directories. In the gfilenotify case it shall work, because glib's implementation uses polling, when other mechanisms fail. file-notify-supported-p is not such clever yet. But users of filenotify.el shall apply this function already, for the future when file-notify-supported-p improves. > Davis Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-22 18:28 ` filenotify.el Michael Albinus @ 2013-07-22 19:00 ` Stefan Monnier 2013-07-23 6:57 ` filenotify.el Michael Albinus 0 siblings, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-07-22 19:00 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel >> Why not just let the error from the underlying notification request >> appear? (This is the usual bit about "don't call stat(2) before >> open(2); just deal with failures from the latter".) > That would be possible, yes. But I hope to improve > file-notify-supported-p, that it could also return a correct answer in > case the underlying library does not support the filesystem in question. But if you can do that for file-notify-supported-p, presumably you can also arrange for file-notify-add-watch to fail in those cases. I agree with Davis that in general it's better to run file-notify-add-watch and handle any error it might signal, than to use a function like file-notify-supported-p. The only case where file-notify-supported-p makes sense is when you want to know if file-notify-add-watch would work before you know whether you want to call file-notify-add-watch. Can't think of too many situations where this would be the case. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-22 19:00 ` filenotify.el Stefan Monnier @ 2013-07-23 6:57 ` Michael Albinus 2013-07-23 13:08 ` filenotify.el Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-07-23 6:57 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > The only case where file-notify-supported-p makes sense is when you want > to know if file-notify-add-watch would work before you know whether you > want to call file-notify-add-watch. Can't think of too many situations > where this would be the case. It is more simple to implement for some Tramp file name handlers. For example, in the smb case I have mapped file-notify-supported-p to ignore. But of course I could implement it differently, let file-notify-add-watch return with a file-notify-error in that case. I have no heavy preference for or against file-notify-supported-p. > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 6:57 ` filenotify.el Michael Albinus @ 2013-07-23 13:08 ` Stefan Monnier 2013-07-23 13:34 ` filenotify.el Michael Albinus 0 siblings, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-07-23 13:08 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > It is more simple to implement for some Tramp file name handlers. For > example, in the smb case I have mapped file-notify-supported-p to > ignore. But of course I could implement it differently, let > file-notify-add-watch return with a file-notify-error in that case. I think it's not an either/or situation: it's important for file-notify-add-watch to return an error if it is not supported for that file, regardless of the existence of file-notify-supported-p. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 13:08 ` filenotify.el Stefan Monnier @ 2013-07-23 13:34 ` Michael Albinus 2013-07-23 13:57 ` filenotify.el Stefan Monnier 2013-07-23 16:10 ` filenotify.el Glenn Morris 0 siblings, 2 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-23 13:34 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> It is more simple to implement for some Tramp file name handlers. For >> example, in the smb case I have mapped file-notify-supported-p to >> ignore. But of course I could implement it differently, let >> file-notify-add-watch return with a file-notify-error in that case. > > I think it's not an either/or situation: it's important for > file-notify-add-watch to return an error if it is not supported for that > file, regardless of the existence of file-notify-supported-p. I haven't meant to let behave file-notify-add-watch to return an error just because of this. Of course, it shall return file-notify-error anyway (marker to myself: we still must change it in w32notify.c). This shall be checked in corresponding ert tests (next marker to myself). Btw, file-notify-supported-p would ease to skip ert tests, if file notification is not available for the local or remote case. > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 13:34 ` filenotify.el Michael Albinus @ 2013-07-23 13:57 ` Stefan Monnier 2013-07-23 14:13 ` filenotify.el Michael Albinus 2013-07-23 16:10 ` filenotify.el Glenn Morris 1 sibling, 1 reply; 50+ messages in thread From: Stefan Monnier @ 2013-07-23 13:57 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > Btw, file-notify-supported-p would ease to skip ert tests, if file > notification is not available for the local or remote case. I don't see why. You can just as well say that "failure for lack of support" is an acceptable result. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 13:57 ` filenotify.el Stefan Monnier @ 2013-07-23 14:13 ` Michael Albinus 2013-07-23 14:23 ` filenotify.el Stefan Monnier 0 siblings, 1 reply; 50+ messages in thread From: Michael Albinus @ 2013-07-23 14:13 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Btw, file-notify-supported-p would ease to skip ert tests, if file >> notification is not available for the local or remote case. > > I don't see why. You can just as well say that "failure for lack of > support" is an acceptable result. Of course. I have just said, it would be more convenient to write such tests with file-notify-supported-p, that's all. But maybe we should not design wrt to test cases :-) As said, I don't care too much whether we keep file-notify-supported-p. Your decision ... > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 14:13 ` filenotify.el Michael Albinus @ 2013-07-23 14:23 ` Stefan Monnier 2013-07-23 15:31 ` filenotify.el Davis Herring 2013-07-24 14:01 ` filenotify.el Michael Albinus 0 siblings, 2 replies; 50+ messages in thread From: Stefan Monnier @ 2013-07-23 14:23 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, emacs-devel > As said, I don't care too much whether we keep file-notify-supported-p. > Your decision ... I think we should try to live without it. If/when it proves necessary/useful, we can re-add it. Stefan ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 14:23 ` filenotify.el Stefan Monnier @ 2013-07-23 15:31 ` Davis Herring 2013-07-24 9:14 ` filenotify.el Michael Albinus 2013-08-02 7:10 ` filenotify.el Michael Albinus 2013-07-24 14:01 ` filenotify.el Michael Albinus 1 sibling, 2 replies; 50+ messages in thread From: Davis Herring @ 2013-07-23 15:31 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, Michael Albinus, emacs-devel >> As said, I don't care too much whether we keep file-notify-supported-p. >> Your decision ... > > I think we should try to live without it. If/when it proves > necessary/useful, we can re-add it. An addendum to my own agitation: if there's a way to prevent gfilenotify from polling (or if we add Lisp polling to filenotify.el in the future), `file-notify-add-watch' could benefit from a don't-poll flag, either as an additional argument or as a new accepted symbol in FLAGS. That way we can (probably) also avoid having a `file-notify-supported-without-polling-p'. Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 15:31 ` filenotify.el Davis Herring @ 2013-07-24 9:14 ` Michael Albinus 2013-08-02 7:10 ` filenotify.el Michael Albinus 1 sibling, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-24 9:14 UTC (permalink / raw) To: Davis Herring; +Cc: Rüdiger Sonderfeld, Stefan Monnier, emacs-devel Davis Herring <herring@lanl.gov> writes: > An addendum to my own agitation: if there's a way to prevent gfilenotify > from polling (or if we add Lisp polling to filenotify.el in the future), > `file-notify-add-watch' could benefit from a don't-poll flag, either as > an additional argument or as a new accepted symbol in FLAGS. I'll check. There is the macro G_IS_POLL_FILE_MONITOR in gio. Maybe it can be used to implement such a flag in gfilenotify.c. However, I would rather implement it as a defcustom than as additional argument to file-notify-add-watch. Then you could decide yourself, whether you want polling, or not. > Davis Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 15:31 ` filenotify.el Davis Herring 2013-07-24 9:14 ` filenotify.el Michael Albinus @ 2013-08-02 7:10 ` Michael Albinus 1 sibling, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-08-02 7:10 UTC (permalink / raw) To: Davis Herring; +Cc: Rüdiger Sonderfeld, Stefan Monnier, emacs-devel Davis Herring <herring@lanl.gov> writes: > An addendum to my own agitation: if there's a way to prevent gfilenotify > from polling (or if we add Lisp polling to filenotify.el in the future), > `file-notify-add-watch' could benefit from a don't-poll flag, either as > an additional argument or as a new accepted symbol in FLAGS. That way > we can (probably) also avoid having a > `file-notify-supported-without-polling-p'. gfilenotify.c uses g_file_monitor from glib/gio. This does polling for mounted objects only in case the object to be watched is a regular file. For directories, polling is not supported (and the function returns an error in case there is no native file notification mechanism for that directory). filenotify.el tries always to watch directories. No polling therefore, at least for the time being. Whether we want introduce explicit polling depends on the request from users. For now, I have no plans. It might be different when the file/directory to be watched is located on a remote host. Then it depends on the implementation of the respective file handler, whether it uses polling, or not. > Davis Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 14:23 ` filenotify.el Stefan Monnier 2013-07-23 15:31 ` filenotify.el Davis Herring @ 2013-07-24 14:01 ` Michael Albinus 1 sibling, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-24 14:01 UTC (permalink / raw) To: Stefan Monnier; +Cc: Rüdiger Sonderfeld, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > I think we should try to live without it. If/when it proves > necessary/useful, we can re-add it. Done. Also fixed in test/automated/file-notify-tests.el. > Stefan Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 13:34 ` filenotify.el Michael Albinus 2013-07-23 13:57 ` filenotify.el Stefan Monnier @ 2013-07-23 16:10 ` Glenn Morris 2013-07-23 16:58 ` filenotify.el Michael Albinus 1 sibling, 1 reply; 50+ messages in thread From: Glenn Morris @ 2013-07-23 16:10 UTC (permalink / raw) To: Michael Albinus; +Cc: Rüdiger Sonderfeld, Stefan Monnier, emacs-devel Michael Albinus wrote: > Btw, file-notify-supported-p would ease to skip ert tests, if file > notification is not available for the local or remote case. The ert tests are all broken now that the variable file-notify-support has been removed (sounds like maybe you know this already?). ^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: filenotify.el 2013-07-23 16:10 ` filenotify.el Glenn Morris @ 2013-07-23 16:58 ` Michael Albinus 0 siblings, 0 replies; 50+ messages in thread From: Michael Albinus @ 2013-07-23 16:58 UTC (permalink / raw) To: Glenn Morris; +Cc: Rüdiger Sonderfeld, Stefan Monnier, emacs-devel Glenn Morris <rgm@gnu.org> writes: > The ert tests are all broken now that the variable file-notify-support > has been removed (sounds like maybe you know this already?). Yes. I have fixed this in my local repository; but I was waiting for the final decision. Too much hassle just now due to other things (@work); I guess there's time to work on it tomorrow morning. Sorry for the inconvenience. Best regards, Michael. ^ permalink raw reply [flat|nested] 50+ messages in thread
end of thread, other threads:[~2013-08-02 7:10 UTC | newest] Thread overview: 50+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-06-25 12:02 filenotify.el Michael Albinus 2013-06-25 16:25 ` filenotify.el Rüdiger Sonderfeld 2013-06-25 19:00 ` filenotify.el Michael Albinus 2013-06-25 19:20 ` filenotify.el Eli Zaretskii 2013-06-25 19:27 ` filenotify.el Michael Albinus 2013-06-25 20:14 ` filenotify.el Eli Zaretskii 2013-06-26 6:06 ` filenotify.el Michael Albinus 2013-06-26 0:11 ` filenotify.el Stefan Monnier 2013-06-26 6:21 ` filenotify.el Michael Albinus 2013-06-26 13:04 ` filenotify.el Stefan Monnier 2013-06-26 14:15 ` filenotify.el Michael Albinus 2013-06-26 14:28 ` filenotify.el Stefan Monnier 2013-06-26 14:37 ` filenotify.el Michael Albinus 2013-06-26 15:57 ` filenotify.el Eli Zaretskii 2013-06-26 19:59 ` filenotify.el Stefan Monnier 2013-06-26 20:28 ` filenotify.el Michael Albinus 2013-06-26 0:45 ` filenotify.el Rüdiger Sonderfeld 2013-06-26 6:40 ` filenotify.el Michael Albinus 2013-06-26 7:50 ` About `<prefix>--' (was Re: filenotify.el) Stephen Berman 2013-06-26 13:06 ` Stefan Monnier 2013-06-26 22:36 ` Stephen Berman 2013-06-27 1:39 ` Stefan Monnier 2013-06-27 23:19 ` Josh 2013-06-28 3:00 ` Xue Fuqiao 2013-06-28 22:54 ` Stefan Monnier 2013-06-28 23:50 ` Xue Fuqiao 2013-06-29 2:06 ` Stefan Monnier 2013-06-28 21:59 ` Richard Stallman 2013-06-30 18:50 ` Josh 2013-06-27 12:18 ` filenotify.el (2) Michael Albinus 2013-07-04 9:54 ` Michael Albinus 2013-07-17 13:52 ` filenotify.el Rüdiger Sonderfeld 2013-07-17 14:54 ` filenotify.el Michael Albinus 2013-07-17 16:21 ` filenotify.el Rüdiger Sonderfeld 2013-07-18 10:10 ` filenotify.el Michael Albinus 2013-07-22 18:17 ` filenotify.el Davis Herring 2013-07-22 18:28 ` filenotify.el Michael Albinus 2013-07-22 19:00 ` filenotify.el Stefan Monnier 2013-07-23 6:57 ` filenotify.el Michael Albinus 2013-07-23 13:08 ` filenotify.el Stefan Monnier 2013-07-23 13:34 ` filenotify.el Michael Albinus 2013-07-23 13:57 ` filenotify.el Stefan Monnier 2013-07-23 14:13 ` filenotify.el Michael Albinus 2013-07-23 14:23 ` filenotify.el Stefan Monnier 2013-07-23 15:31 ` filenotify.el Davis Herring 2013-07-24 9:14 ` filenotify.el Michael Albinus 2013-08-02 7:10 ` filenotify.el Michael Albinus 2013-07-24 14:01 ` filenotify.el Michael Albinus 2013-07-23 16:10 ` filenotify.el Glenn Morris 2013-07-23 16:58 ` filenotify.el Michael Albinus
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).