22
|
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
2 ;;
|
|
3 ;; File: dired-sex.el
|
|
4 ;; Dired Version: $Revision: 1.1 $
|
|
5 ;; RCS:
|
|
6 ;; Description: Marking files according to sexpressions. Sorry.
|
|
7 ;; Created: Wed Sep 14 01:30:43 1994 by sandy on ibm550
|
|
8 ;;
|
|
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
10
|
|
11 (provide 'dired-sex)
|
|
12 (require 'dired)
|
|
13
|
|
14 (defvar dired-sexpr-history-symbol nil
|
|
15 "History of sexpr used to mark files in dired.")
|
|
16
|
|
17 ;;; Marking files according to sexpr's
|
|
18
|
|
19 (defmacro dired-parse-ls ()
|
|
20 ;; Sets vars
|
|
21 ;; inode s mode nlink uid gid size time name sym
|
|
22 ;; (probably let-bound in caller) according to current file line.
|
|
23 ;; Returns t for succes, nil if this is no file line.
|
|
24 ;; Upon success, all variables are set, either to nil or the
|
|
25 ;; appropriate value, so they need not be initialized.
|
|
26 ;; Moves point within the current line to the end of the file name.
|
|
27 '(let ((bol (progn (beginning-of-line) (point)))
|
|
28 (eol (save-excursion (skip-chars-forward "^\n\r") (point))))
|
|
29 (if (re-search-forward dired-re-month-and-time eol t)
|
|
30 (let ((mode-len 10) ; length of mode string
|
|
31 (tstart (progn (goto-char (match-beginning 0))
|
|
32 (skip-chars-forward " ")
|
|
33 (point)))
|
|
34 (fstart (match-end 0))
|
|
35 pos)
|
|
36 (goto-char (1+ bol))
|
|
37 (skip-chars-forward " \t")
|
|
38 ;; This subdir had better have been created with the current
|
|
39 ;; setting of actual switches. Otherwise, we can't parse.
|
|
40 (cond
|
|
41 ((and (or (memq ?k dired-internal-switches)
|
|
42 (memq ?s dired-internal-switches))
|
|
43 (memq ?i dired-internal-switches))
|
|
44 (setq pos (point))
|
|
45 (skip-chars-forward "0-9")
|
|
46 (if (setq inode (and (/= pos (point)) (string-to-int
|
|
47 (buffer-substring
|
|
48 pos (point)))))
|
|
49 (progn
|
|
50 (skip-chars-forward " ")
|
|
51 (setq pos (point))
|
|
52 (skip-chars-forward "0-9")
|
|
53 (setq s (and (/= pos (point)) (string-to-int
|
|
54 (buffer-substring
|
|
55 pos (point))))))
|
|
56 (setq s nil)))
|
|
57 ((or (memq ?s dired-internal-switches)
|
|
58 (memq ?k dired-internal-switches))
|
|
59 (setq pos (point))
|
|
60 (skip-chars-forward "0-9")
|
|
61 (setq s (and (/= pos (point)) (string-to-int
|
|
62 (buffer-substring
|
|
63 pos (point))))
|
|
64 inode nil))
|
|
65 ((memq ?i dired-internal-switches)
|
|
66 (setq pos (point))
|
|
67 (skip-chars-forward "0-9")
|
|
68 (setq inode (and (/= pos (point)) (string-to-int
|
|
69 (buffer-substring
|
|
70 pos (point))))
|
|
71 s nil))
|
|
72 (t
|
|
73 (setq s nil
|
|
74 inode nil)))
|
|
75 (skip-chars-forward " 0-9") ; in case of junk
|
|
76 (setq mode (buffer-substring (point) (+ mode-len (point))))
|
|
77 (forward-char mode-len)
|
|
78 (setq nlink (read (current-buffer)))
|
|
79 (or (integerp nlink) (setq nlink nil))
|
|
80 (setq uid (buffer-substring (point) (progn
|
|
81 (skip-chars-forward "^ ")
|
|
82 (point))))
|
|
83 (goto-char tstart)
|
|
84 (skip-chars-backward " ")
|
|
85 (setq pos (point))
|
|
86 (skip-chars-backward "0-9")
|
|
87 (if (= pos (point))
|
|
88 (setq size nil)
|
|
89 (setq size (string-to-int (buffer-substring (point) pos))))
|
|
90 (skip-chars-backward " ")
|
|
91 ;; if no gid is displayed, gid will be set to uid
|
|
92 ;; but user will then not reference it anyway in PREDICATE.
|
|
93 (setq gid (buffer-substring (point) (progn
|
|
94 (skip-chars-backward "^ ")
|
|
95 (point)))
|
|
96 time (buffer-substring tstart
|
|
97 (progn
|
|
98 (goto-char fstart)
|
|
99 (skip-chars-backward " ")
|
|
100 (point)))
|
|
101 name (buffer-substring
|
|
102 fstart
|
|
103 (or (dired-move-to-end-of-filename t)
|
|
104 (point)))
|
|
105 sym (and (looking-at "[/*@#=|]? -> ")
|
|
106 (buffer-substring (match-end 0)
|
|
107 eol)))
|
|
108 t)))) ; return t if parsing was a success
|
|
109
|
|
110
|
|
111 (defun dired-mark-sexp (predicate &optional unflag-p)
|
|
112 "Mark files for which PREDICATE returns non-nil.
|
|
113 With a prefix arg, unflag those files instead.
|
|
114
|
|
115 PREDICATE is a lisp expression that can refer to the following symbols:
|
|
116
|
|
117 inode [integer] the inode of the file (only for ls -i output)
|
|
118 s [integer] the size of the file for ls -s output
|
|
119 (ususally in blocks or, with -k, in KByte)
|
|
120 mode [string] file permission bits, e.g. \"-rw-r--r--\"
|
|
121 nlink [integer] number of links to file
|
|
122 uid [string] owner
|
|
123 gid [string] group (If the gid is not displayed by ls,
|
|
124 this will still be set (to the same as uid))
|
|
125 size [integer] file size in bytes
|
|
126 time [string] the time that ls displays, e.g. \"Feb 12 14:17\"
|
|
127 name [string] the name of the file
|
|
128 sym [string] if file is a symbolic link, the linked-to name, else nil.
|
|
129
|
|
130 For example, use
|
|
131
|
|
132 (equal 0 size)
|
|
133
|
|
134 to mark all zero length files."
|
|
135 ;; Using sym="" instead of nil avoids the trap of
|
|
136 ;; (string-match "foo" sym) into which a user would soon fall.
|
|
137 ;; No! Want to be able look for symlinks pointing to the empty string.
|
|
138 ;; Can happen. Also, then I can do an (if sym ...) structure. --sandy
|
|
139 ;; Give `equal' instead of `=' in the example, as this works on
|
|
140 ;; integers and strings.
|
|
141 (interactive
|
|
142 (list
|
|
143 (read
|
|
144 (dired-read-with-history "Mark if (lisp expr): " nil
|
|
145 'dired-sexpr-history))
|
|
146 current-prefix-arg))
|
|
147 (message "%s" predicate)
|
|
148 (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char))
|
|
149 inode s mode nlink uid gid size time name sym)
|
|
150 (dired-mark-if (save-excursion
|
|
151 (and (dired-parse-ls)
|
|
152 (eval predicate)))
|
|
153 (format "'%s file" predicate)))
|
|
154 (dired-update-mode-line-modified t))
|
|
155
|
|
156 ;;; end of dired-sex.el
|