[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Filtering files with Ediff
From: |
drkm |
Subject: |
Filtering files with Ediff |
Date: |
Wed, 05 Jan 2005 00:11:17 +0100 |
User-agent: |
Gnus/5.110003 (No Gnus v0.3) Emacs/21.3.50 (windows-nt) |
Hello
I looked for a way to filter out some files from those `edirs'
uses. Basically, I want to filter out files contained in my
.cvsignore files, when applicable. .cvsignore files contain shell
file patterns (filenames with wildcards).
The functions used by `edirs' take a regexp to select files to be
diff-ed. But wildcards interact not well with regexp, as far as I
know. I know `wildcard-to-regexp', but it takes a single pattern. So
I have to construct the complete regexp by concatenate all regexps,
separating them by "\\|". It's not very efficient.
Furthemore, I think a more powerfull filtering functionality could
be intresting when diff-ing directories. So I modify
`ediff-intersect-directories' to filter out the directories contents
(the files in these directories) in function of user-provided filters.
I also added some usefull filters (filtering strings, regexps,
wildcards and in function of .cvsignore files). So I have this in my
.emacs to filter out ".~" and from .cvsignore files:
;; I have (setq backup-directory-alist '(("." . ".~"))) somewhere.
(setq ediff-filter-out-names-data '(".~")
ediff-dir-contents-filters '(ediff-filter-out-names
ediff-filter-out-cvsignore))
Does this seem to be usefull ?
--drkm
*** ediff-diff.el.old Thu Dec 23 07:01:56 2004
--- ediff-diff.el Thu Dec 30 08:24:14 2004
***************
*** 1338,1343 ****
--- 1338,1350 ----
(append ediff-cmp-options (list f1 f2)))))
(and (numberp res) (eq res 0))))
+ (defun ediff-same-file-contents-3 (f1 f2 &optional f3)
+ "Return t if F1, F2 and F3 (if applicable) have identical contents."
+ (and (ediff-same-file-contents file1 file2)
+ (or (null file3)
+ (and (ediff-same-file-contents file1 file3)
+ (ediff-same-file-contents file2 file3)))))
+
;;; Local Variables:
;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
*** ediff-mult.el.old Thu Dec 23 07:01:56 2004
--- ediff-mult.el Tue Jan 4 23:44:10 2005
***************
*** 508,513 ****
--- 508,620 ----
ediff-membership-code2
ediff-membership-code3))
+ (defcustom ediff-dir-contents-filters nil
+ "List of function, used to filter directory contents for dir operations.
+
+ These functions are called with 3 or 4 arguments. The first,
+ CONTENT, is the list to filter (a list of filenames). The
+ remaining arguments, DIR1, DIR2 and DIR3 (optional), are the
+ directories whose are extracted CONTENT.
+
+ CONTENT contains only the files that are commons to these 2 (or
+ 3) directories. The result of the call is used as the new
+ contents list. Functions are called from the head to the tail of
+ the list."
+ :type '(repeat function)
+ :group 'ediff)
+
+ (defcustom ediff-filter-out-names-data nil
+ "List of names to filter out. See `ediff-dir-contents-filters'."
+ :type '(repeat string)
+ :group 'ediff)
+
+ (defun ediff-filter-out-names (content &optional dir1 dir2 dir3)
+ "Filter out names contained in `ediff-filter-out-names-data'."
+ (dolist (name ediff-filter-out-names-data content)
+ (setq content (delete name content))))
+
+ (defcustom ediff-filter-out-regexps-data nil
+ "List of regexps to filter out. See `ediff-dir-contents-filters'."
+ :type '(repeat regexp)
+ :group 'ediff)
+
+ (defun ediff-filter-out-regexps (content &optional dir1 dir2 dir3)
+ "Filter out regexps contained in `ediff-filter-out-regexps-data'."
+ (dolist (regexp ediff-filter-out-regexps-data content)
+ ;; Not use CL here.
+ ;; (setq content (delete* regexp content :test 'string-match))))
+ (setq content (let* ((res '(dummy))
+ (i res))
+ (dolist (c content (cdr res))
+ (unless (string-match regexp c)
+ (setcdr i (cons c nil))
+ (setq i (cdr i))))))))
+
+ (defcustom ediff-filter-out-wildcards-data nil
+ "List of wildcards to filter out. See `ediff-dir-contents-filters'."
+ :type '(repeat string)
+ :group 'ediff)
+
+ (defun ediff-filter-out-wildcards (content &optional dir1 dir2 dir3)
+ "Filter out wildcards contained in `ediff-filter-out-wildcards-data'."
+ (let ((matches (apply 'nconc (mapcar 'file-expand-wildcards
+ ediff-filter-out-wildcards-data))))
+ (dolist (match matches content)
+ (setq content (delete match content)))))
+
+ (defun ediff-filter-out-cvsignore (content dir1 dir2 &optional dir3)
+ "Filter out patterns found in a .cvsignore file."
+ (let ((ediff-filter-out-wildcards-data (ediff-get-cvsignore-wildcards
+ dir1 dir2 dir3)))
+ (ediff-filter-out-wildcards content dir1 dir2 dir3)))
+
+ (defun ediff-get-cvsignore-wildcards (dir1 dir2 &optional dir3)
+ "Get wildcards contained in a .cvsignore file.
+ Return a list of strings. Each element is a pattern from the
+ .cvsignore file.
+ The .cvsignore file is search in DIR1, DIR2 and DIR3 (if
+ applicable). IF none is found, return nil. If multiple file are
+ found, they must be exactly identicals."
+ (let ((files (delq nil (mapcar (lambda (dir)
+ (let ((file (concat dir ".cvsignore")))
+ (when (file-exists-p file)
+ file)))
+ (if (stringp dir3)
+ (list dir1 dir2 dir3)
+ (list dir1 dir2))))))
+ (when (and (> (length files) 1)
+ (not (apply 'ediff-same-file-content-3 files)))
+ (error ".cvsignore files are differents! %S" files))
+ (when files
+ (split-string (with-temp-buffer
+ (insert-file-contents (car files))
+ (buffer-string))
+ "[ \n]+" t))))
+
+ (defun ediff-get-dirs-contents (dir1 dir2 &optional dir3 regexp)
+ "Get contents of these directories.
+ Mainly a utility routine for `ediff-intersect-directories'. Use
+ REGEXP if specified to select only files matching. Use
+ `ediff-dir-contents-filters' to filter the result furthemore."
+ (setq dir1 (file-name-as-directory dir1)
+ dir2 (file-name-as-directory dir2)
+ dir3 (and (stringp dir3) (file-name-as-directory dir3)))
+ (if (stringp dir3)
+ (list (cons dir1 (ediff-get-dirs-contents-1 dir1 dir2 dir3 regexp))
+ (cons dir2 (ediff-get-dirs-contents-1 dir2 dir1 dir3 regexp))
+ (cons dir3 (ediff-get-dirs-contents-1 dir3 dir1 dir2 regexp)))
+ (list (cons dir1 (ediff-get-dirs-contents-1 dir1 dir2 dir3 regexp))
+ (cons dir2 (ediff-get-dirs-contents-1 dir2 dir1 dir3 regexp)))))
+
+ (defun ediff-get-dirs-contents-1 (dir1 dir2 &optional dir3 regexp)
+ (mapcar (lambda (f)
+ (ediff-add-slash-if-directory dir1 f))
+ (let* ((default-directory (expand-file-name dir1))
+ (res (directory-files dir1 nil regexp)))
+ (setq res (delete "." (delete ".." res)))
+ (dolist (filter ediff-dir-contents-filters res)
+ (setq res (funcall filter res dir1 dir2 dir3))))))
+
;; DIR1, DIR2, DIR3 are directories. DIR3 can be nil.
;; OUTPUT-DIR is a directory for auto-storing the results of merge jobs.
;; Can be nil.
***************
*** 548,573 ****
(setq comparison-func (or comparison-func 'string=))
(let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 common-part difflist)
! (setq auxdir1 (file-name-as-directory dir1)
! lis1 (directory-files auxdir1 nil regexp)
! lis1 (delete "." lis1)
! lis1 (delete ".." lis1)
! lis1 (mapcar
! (lambda (elt)
! (ediff-add-slash-if-directory auxdir1 elt))
! lis1)
! auxdir2 (file-name-as-directory dir2)
! lis2 (mapcar
! (lambda (elt)
! (ediff-add-slash-if-directory auxdir2 elt))
! (directory-files auxdir2 nil regexp)))
!
! (if (stringp dir3)
! (setq auxdir3 (file-name-as-directory dir3)
! lis3 (mapcar
! (lambda (elt)
! (ediff-add-slash-if-directory auxdir3 elt))
! (directory-files auxdir3 nil regexp))))
(if (ediff-nonempty-string-p merge-autostore-dir)
(setq merge-autostore-dir
--- 655,664 ----
(setq comparison-func (or comparison-func 'string=))
(let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 common-part difflist)
! (let ((res (ediff-get-dirs-contents dir1 dir2 dir3 regexp)))
! (setq auxdir1 (car (nth 0 res)) lis1 (cdr (nth 0 res))
! auxdir2 (car (nth 1 res)) lis2 (cdr (nth 1 res))
! auxdir3 (car (nth 2 res)) lis3 (cdr (nth 2 res))))
(if (ediff-nonempty-string-p merge-autostore-dir)
(setq merge-autostore-dir
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Filtering files with Ediff,
drkm <=