diff options
| author | Richard M. Stallman | 1993-06-26 04:01:50 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-06-26 04:01:50 +0000 |
| commit | 198d5c0098044d63124902ad8b1b617b5af59e04 (patch) | |
| tree | ead45b4f34e9fc52a071451fe21d38616e242b9d | |
| parent | af2a85fe3903e1c8ee2de2dd72459e4471f5260c (diff) | |
| download | emacs-198d5c0098044d63124902ad8b1b617b5af59e04.tar.gz emacs-198d5c0098044d63124902ad8b1b617b5af59e04.zip | |
(vc-rcs-status): New variable.
(vc-mode-line): Display the lock status and head version.
(vc-rcs-status, vc-rcs-glean-field): New function.
| -rw-r--r-- | lisp/vc-hooks.el | 136 |
1 files changed, 133 insertions, 3 deletions
diff --git a/lisp/vc-hooks.el b/lisp/vc-hooks.el index 83588dcb4fe..e5d71471a27 100644 --- a/lisp/vc-hooks.el +++ b/lisp/vc-hooks.el | |||
| @@ -38,6 +38,10 @@ when creating new masters.") | |||
| 38 | "*If non-nil, backups of registered files are made according to | 38 | "*If non-nil, backups of registered files are made according to |
| 39 | the make-backup-files variable. Otherwise, prevents backups being made.") | 39 | the make-backup-files variable. Otherwise, prevents backups being made.") |
| 40 | 40 | ||
| 41 | (defvar vc-rcs-status t | ||
| 42 | "*If non-nil, revision and locks on RCS working file displayed in modeline. | ||
| 43 | Otherwise, not displayed.") | ||
| 44 | |||
| 41 | ;; Tell Emacs about this new kind of minor mode | 45 | ;; Tell Emacs about this new kind of minor mode |
| 42 | (if (not (assoc 'vc-mode minor-mode-alist)) | 46 | (if (not (assoc 'vc-mode minor-mode-alist)) |
| 43 | (setq minor-mode-alist (cons '(vc-mode vc-mode) | 47 | (setq minor-mode-alist (cons '(vc-mode vc-mode) |
| @@ -126,13 +130,139 @@ visiting FILE." | |||
| 126 | (interactive (list buffer-file-name nil)) | 130 | (interactive (list buffer-file-name nil)) |
| 127 | (let ((vc-type (vc-backend-deduce file))) | 131 | (let ((vc-type (vc-backend-deduce file))) |
| 128 | (if vc-type | 132 | (if vc-type |
| 129 | (progn | 133 | (setq vc-mode |
| 130 | (setq vc-mode | 134 | (concat (if (and vc-rcs-status (eq vc-type 'RCS)) |
| 131 | (concat " " (or label (symbol-name vc-type)))))) | 135 | (vc-rcs-status file)) |
| 136 | " " (or label (symbol-name vc-type))))) | ||
| 132 | ;; force update of mode line | 137 | ;; force update of mode line |
| 133 | (set-buffer-modified-p (buffer-modified-p)) | 138 | (set-buffer-modified-p (buffer-modified-p)) |
| 134 | vc-type)) | 139 | vc-type)) |
| 135 | 140 | ||
| 141 | (defun vc-rcs-status (file) | ||
| 142 | ;; Return string " [LOCKERS:]REV" if FILE under RCS control, otherwise nil, | ||
| 143 | ;; for placement in modeline by `vc-mode-line'. | ||
| 144 | |||
| 145 | ;; If FILE is not locked then return just " REV", where | ||
| 146 | ;; REV is the number of last revision checked in. If the FILE is locked | ||
| 147 | ;; then return *all* the locks currently set, in a single string of the | ||
| 148 | ;; form " LOCKER1:REV1 LOCKER2:REV2 ..." | ||
| 149 | |||
| 150 | ;; Algorithm: | ||
| 151 | |||
| 152 | ;; 1. Check for master file corresponding to FILE being visited in | ||
| 153 | ;; subdirectory RCS of current directory and then, if not found there, in | ||
| 154 | ;; the current directory. some of the vc-hooks machinery could be used | ||
| 155 | ;; here. | ||
| 156 | ;; | ||
| 157 | ;; 2. Insert the header, first 200 characters, of master file into a work | ||
| 158 | ;; buffer. | ||
| 159 | ;; | ||
| 160 | ;; 3. Search work buffer for line starting with "date" indicating enough | ||
| 161 | ;; of header was included; if not found, then successive increments of 100 | ||
| 162 | ;; characters are inserted until "date" is located or 1000 characters is | ||
| 163 | ;; reached. | ||
| 164 | ;; | ||
| 165 | ;; 4. Search work buffer for line starting with "locks" and *not* followed | ||
| 166 | ;; immediately by a semi-colon; this indicates that locks exist; it extracts | ||
| 167 | ;; all the locks currently enabled and removes controls characters | ||
| 168 | ;; separating them, like newlines; the string " user1:revision1 | ||
| 169 | ;; user2:revision2 ..." is returned. | ||
| 170 | ;; | ||
| 171 | ;; 5. If "locks;" is found instead, indicating no locks, then search work | ||
| 172 | ;; buffer for lines starting with string "head" and "branch" and parses | ||
| 173 | ;; their contents; if contents of branch is non-nil then it is returned | ||
| 174 | ;; otherwise the contents of head is returned either as string " revision". | ||
| 175 | |||
| 176 | ;; Limitations: | ||
| 177 | |||
| 178 | ;; The output doesn't show which version you are actually looking at. | ||
| 179 | ;; The modeline can get quite cluttered when there are multiple locks. | ||
| 180 | |||
| 181 | ;; Make sure name is expanded -- not needed? | ||
| 182 | (setq file (expand-file-name file)) | ||
| 183 | |||
| 184 | (let (master found locks head branch status (eof 200)) | ||
| 185 | |||
| 186 | ;; Find the name of the master file -- perhaps use `vc-name'? | ||
| 187 | (setq master (concat (file-name-directory file) "RCS/" | ||
| 188 | (file-name-nondirectory file) ",v")) | ||
| 189 | |||
| 190 | ;; If master file exists, then parse its contents, otherwise we return the | ||
| 191 | ;; nil value of this if form. | ||
| 192 | (if (or (file-readable-p master) | ||
| 193 | (file-readable-p (setq master (concat file ",v")))) ; current dir? | ||
| 194 | |||
| 195 | (save-excursion | ||
| 196 | |||
| 197 | ;; Create work buffer. | ||
| 198 | (set-buffer (get-buffer-create "*vc-rcs-status*")) | ||
| 199 | (setq buffer-read-only nil | ||
| 200 | default-directory (file-name-directory master)) | ||
| 201 | (erase-buffer) | ||
| 202 | |||
| 203 | ;; Limit search to header. | ||
| 204 | (insert-file-contents master nil 0 eof) | ||
| 205 | (goto-char (point-min)) | ||
| 206 | |||
| 207 | ;; Check if we have enough of the header. If not, then keep | ||
| 208 | ;; including more until enough or until 1000 chars is reached. | ||
| 209 | (setq found (re-search-forward "^date" nil t)) | ||
| 210 | |||
| 211 | (while (and (not found) (<= eof 1000)) | ||
| 212 | (goto-char (point-max)) | ||
| 213 | (insert-file-contents master nil (+ eof 1) (setq eof (+ eof 100))) | ||
| 214 | (goto-char (point-min)) | ||
| 215 | (setq found (re-search-forward "^date" nil t))) | ||
| 216 | |||
| 217 | ;; If we located "^date" we can extract the status information, | ||
| 218 | ;; otherwise we return `status' which was initialized to nil. | ||
| 219 | (if found | ||
| 220 | (progn | ||
| 221 | (goto-char (point-min)) | ||
| 222 | |||
| 223 | ;; First see if any revisions have any locks on them. | ||
| 224 | (if (re-search-forward "^locks[ \t\n\r\f]+\\([^;]*\\)" nil t) | ||
| 225 | |||
| 226 | ;; At least one lock - clean controls characters from text. | ||
| 227 | (save-restriction | ||
| 228 | (narrow-to-region (match-beginning 1) (match-end 1)) | ||
| 229 | (goto-char (point-min)) | ||
| 230 | (while (re-search-forward "[ \t\n\r\f]+" nil t) | ||
| 231 | (replace-match " " t t)) | ||
| 232 | (setq locks (buffer-string))) | ||
| 233 | |||
| 234 | ;; Not locked - find head and branch. | ||
| 235 | ;; ...more information could be extracted here. | ||
| 236 | (setq locks "" | ||
| 237 | head (vc-rcs-glean-field "head") | ||
| 238 | branch (vc-rcs-glean-field "branch"))) | ||
| 239 | |||
| 240 | ;; In case of RCS unlocked files: if non-nil branch is | ||
| 241 | ;; displayed, else if non-nil head is displayed. if both nil, | ||
| 242 | ;; nothing is displayed. In case of RCS locked files: locks | ||
| 243 | ;; is displayed. | ||
| 244 | |||
| 245 | (setq status (concat " " (or branch head locks))))) | ||
| 246 | |||
| 247 | ;; Clean work buffer. | ||
| 248 | (erase-buffer) | ||
| 249 | (set-buffer-modified-p nil) | ||
| 250 | |||
| 251 | ;; Return status, which is nil if "^date" was not located. | ||
| 252 | status)))) | ||
| 253 | |||
| 254 | (defun vc-rcs-glean-field (field) | ||
| 255 | ;; Parse ,v file in current buffer and return contents of FIELD, | ||
| 256 | ;; which should be a field like "head" or "branch", with a | ||
| 257 | ;; revision number as value. | ||
| 258 | ;; Returns nil if FIELD is not found. | ||
| 259 | (goto-char (point-min)) | ||
| 260 | (if (re-search-forward | ||
| 261 | (concat "^" (regexp-quote field) "[ \t\n\r\f]+\\([0-9.]+\\)") | ||
| 262 | nil t) | ||
| 263 | (buffer-substring (match-beginning 1) | ||
| 264 | (match-end 1)))) | ||
| 265 | |||
| 136 | ;;; install a call to the above as a find-file hook | 266 | ;;; install a call to the above as a find-file hook |
| 137 | (defun vc-find-file-hook () | 267 | (defun vc-find-file-hook () |
| 138 | ;; Recompute whether file is version controlled, | 268 | ;; Recompute whether file is version controlled, |