Annotation of 43BSD/contrib/emacs/lisp/files.el, revision 1.1.1.1

1.1       root        1: ;; File input and output commands for Emacs
                      2: ;; Copyright (C) 1985 Richard M. Stallman.
                      3: 
                      4: ;; This file is part of GNU Emacs.
                      5: 
                      6: ;; GNU Emacs is distributed in the hope that it will be useful,
                      7: ;; but WITHOUT ANY WARRANTY.  No author or distributor
                      8: ;; accepts responsibility to anyone for the consequences of using it
                      9: ;; or for whether it serves any particular purpose or works at all,
                     10: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
                     11: ;; License for full details.
                     12: 
                     13: ;; Everyone is granted permission to copy, modify and redistribute
                     14: ;; GNU Emacs, but only under the conditions described in the
                     15: ;; GNU Emacs General Public License.   A copy of this license is
                     16: ;; supposed to have been given to you along with GNU Emacs so you
                     17: ;; can know your rights and responsibilities.  It should be in a
                     18: ;; file named COPYING.  Among other things, the copyright notice
                     19: ;; and this notice must be preserved on all copies.
                     20: 
                     21: 
                     22: (defconst delete-auto-save-files t
                     23:   "*Non-nil means delete a buffer's auto-save file
                     24: when the buffer is saved for real.")
                     25: 
                     26: (defconst make-backup-files t
                     27:   "*Create a backup of each file when it is saved for the first time.
                     28: This can be done by renaming the file or by copying, according to the
                     29: values of  backup-by-copying  and   backup-by-copying-when-linked.")
                     30: 
                     31: (defconst backup-by-copying nil
                     32:  "*Non-nil means create backups of files by copying rather than by renaming.")
                     33: 
                     34: (defconst backup-by-copying-when-linked nil
                     35:  "*Non-nil means create backups of multi-named files by copying
                     36: rather than by renaming.
                     37: This causes the alternate names to refer to the latest version as edited.")
                     38: 
                     39: (defvar version-control nil
                     40:   "*Control use of version numbers for backup files.
                     41: t means make numeric backup versions unconditionally.
                     42: nil means make them for files that have some already.
                     43: never means do not make them.")
                     44: 
                     45: (defvar dired-kept-versions 2
                     46:   "*When cleaning directory, number of versions to keep.")
                     47: 
                     48: (defvar trim-versions-without-asking nil
                     49:   "*If true, deletes excess backup versions silently.
                     50: Otherwise asks confirmation.")
                     51: 
                     52: (defvar kept-old-versions 2
                     53:   "*Number of oldest versions to keep when a new numbered backup is made.")
                     54: 
                     55: (defvar kept-new-versions 2
                     56:   "*Number of newest versions to keep when a new numbered backup is made.
                     57: Includes the new backup.  Must be > 0")
                     58: 
                     59: (defconst require-final-newline nil
                     60:   "*t says silently put a newline at the end whenever a file is saved.
                     61: Non-nil but not t says ask user whether to add a newline in each such case.
                     62: nil means don't add newlines.")
                     63: 
                     64: (defconst auto-save-default t
                     65:   "*t says by default do auto-saving of every file-visiting buffer.")
                     66: 
                     67: (defconst auto-save-visited-file-name nil
                     68:   "*t says auto-save a buffer in the file it is visiting, when practical.
                     69: Normally auto-save files are written under other names.")
                     70: 
                     71: (defconst save-abbrevs t
                     72:   "*Non-nil means save word abbrevs too when files are saved.")
                     73: 
                     74: (defconst find-file-run-dired t
                     75:   "*Non-nil says run dired if find-file is given the name of a directory.")
                     76: 
                     77: (defvar find-file-not-found-hook nil
                     78:   "*If non-nil specifies a function to be called for find-file on nonexistent file.
                     79: This function is called as soon as the error is detected.
                     80: buffer-file-name is already set up.")
                     81: 
                     82: (defvar find-file-hook nil
                     83:   "*If non-nil specifies a function to be called after a buffer
                     84: is found or reverted from a file.
                     85: The buffer's local variables (if any) will have been processed before the
                     86: function is called.")
                     87: 
                     88: (defvar write-file-hook nil
                     89:   "*If non-nil specifies a function to be called before writing out a buffer
                     90: to a file.")
                     91: 
                     92: ;; Avoid losing in versions where CLASH_DETECTION is disabled.
                     93: (or (fboundp 'lock-buffer)
                     94:     (fset 'lock-buffer 'ignore))
                     95: (or (fboundp 'unlock-buffer)
                     96:     (fset 'unlock-buffer 'ignore))
                     97: 
                     98: (defun pwd ()
                     99:   "Show the current default directory."
                    100:   (interactive nil)
                    101:   (message "Directory %s" default-directory))
                    102: 
                    103: (defun cd (dir)
                    104:   "Make DIR become the current buffer's default directory."
                    105:   (interactive "DChange default directory: ")
                    106:   (setq dir (expand-file-name dir))
                    107:   ;; (interactive "D") really doesn't do the right thing at all
                    108:   (or (string-match "/$" dir)
                    109:       (setq dir (concat dir "/")))
                    110:   (if (not (file-directory-p dir))
                    111:       (error "%s is not a directory" dir)
                    112:     (setq default-directory dir))
                    113:   (pwd))
                    114: 
                    115: (defun switch-to-buffer-other-window (buffer)
                    116:   "Select buffer BUFFER in another window."
                    117:   (interactive "BSwitch to buffer in other window: ")
                    118:   (let ((pop-up-windows t))
                    119:     (pop-to-buffer buffer t)))
                    120: 
                    121: (defun find-file (filename)
                    122:   "Edit file FILENAME.
                    123: Switch to a buffer visiting file FILENAME,
                    124: creating one if none already exists."
                    125:   (interactive "FFind file: ")
                    126:   (switch-to-buffer (find-file-noselect filename)))
                    127: 
                    128: (defun find-file-other-window (filename)
                    129:   "Edit file FILENAME, in another window.
                    130: May create a new window, or reuse an existing one;
                    131: see the function display-buffer."
                    132:   (interactive "FFind file in other window: ")
                    133:   (switch-to-buffer-other-window (find-file-noselect filename)))
                    134: 
                    135: (defun find-file-read-only (filename)
                    136:   "Edit file FILENAME but don't save without confirmation.
                    137: Like find-file but marks buffer as read-only."
                    138:   (interactive "fFind file read-only: ")
                    139:   (find-file filename)
                    140:   (setq buffer-read-only t))
                    141: 
                    142: (defun find-alternate-file (filename)
                    143:   "Find file FILENAME, select its buffer, kill previous buffer.
                    144: If the current buffer now contains an empty file that you just visited
                    145: \(presumably by mistake), use this command to visit the file you really want."
                    146:   (interactive "FFind alternate file: ")
                    147:   (if (null buffer-file-name)
                    148:       (error "Non-file buffer"))
                    149:   (and (buffer-modified-p)
                    150:        (not (yes-or-no-p (format "Buffer %s is modified; kill anyway? "
                    151:                                 (buffer-name))))
                    152:        (error "Aborted"))
                    153:   (let ((obuf (current-buffer))
                    154:        (ofile buffer-file-name)
                    155:        (oname (buffer-name)))
                    156:     (rename-buffer " **lose**")
                    157:     (setq buffer-file-name nil)
                    158:     (unwind-protect
                    159:        (progn
                    160:          (unlock-buffer)
                    161:          (find-file filename))
                    162:       (cond ((eq obuf (current-buffer))
                    163:             (setq buffer-file-name ofile)
                    164:             (lock-buffer)
                    165:             (rename-buffer oname))))
                    166:     (kill-buffer obuf)))
                    167: 
                    168: (defvar ask-about-buffer-names nil
                    169:   "*Non-nil means ask user for buffer name when there is a conflict.
                    170: The default is to generate a unique name with no interaction.")
                    171: 
                    172: (defun create-file-buffer (filename)
                    173:   "Creates a suitably named buffer for visiting FILENAME, and returns it."
                    174:   (let ((base (file-name-nondirectory filename)))
                    175:     (if (and (get-buffer base)
                    176:             ask-about-buffer-names)
                    177:        (get-buffer-create
                    178:          (let ((tem (read-string (format
                    179:  "Buffer name \"%s\" is in use; type a new name, or Return to clobber: "
                    180:                                    base))))
                    181:            (if (equal tem "") base tem)))
                    182:       (generate-new-buffer base))))
                    183: 
                    184: (defun find-file-noselect (filename)
                    185:   "Read file FILENAME into a buffer and return the buffer.
                    186: If a buffer exists visiting FILENAME, return that one,
                    187: but verify that the file has not changed since visited or saved.
                    188: The buffer is not selected, just returned to the caller."
                    189:   (if (file-directory-p filename)
                    190:       (if find-file-run-dired
                    191:          (dired-noselect filename)
                    192:        (error "%s is a directory." filename))
                    193:     (let ((buf (get-file-buffer filename))
                    194:          error)
                    195:       (if buf
                    196:          (or (verify-visited-file-modtime buf)
                    197:              (if (not (file-exists-p filename))
                    198:                  (progn (message "Note: file %s no longer exists" filename)
                    199:                         t))
                    200:              (not (yes-or-no-p
                    201:                     (if (buffer-modified-p buf)
                    202:    "File has changed since last visited or saved.  Flush your changes? "
                    203:    "File has changed since last visited or saved.  Read from disk? ")))
                    204:              (save-excursion
                    205:                (set-buffer buf)
                    206:                (revert-buffer t)))
                    207:        (save-excursion
                    208:          (setq buf (create-file-buffer filename)
                    209:                filename (expand-file-name filename))
                    210:          (set-buffer buf)
                    211:          (erase-buffer)
                    212:          (condition-case ()
                    213:              (insert-file-contents filename t)
                    214:            (file-error
                    215:             (setq error t
                    216:                   buffer-file-name filename)
                    217:             (if find-file-not-found-hook
                    218:                 (funcall find-file-not-found-hook))))
                    219:          (setq default-directory (file-name-directory filename))
                    220:          (after-find-file error)))
                    221:       buf)))
                    222: 
                    223: 
                    224: (defun after-find-file (error)
                    225:   "Called after finding a file and by the default revert function.
                    226: Sets buffer mode, parses local variables, calls  find-file-hook."
                    227:   (setq buffer-read-only (not (file-writable-p buffer-file-name)))
                    228:   (if noninteractive
                    229:       nil
                    230:     (message (cond ((not buffer-read-only)
                    231:                    (if error "(New file)" ""))
                    232:                   ((not error)
                    233:                    "File is write protected")
                    234:                   ((file-attributes buffer-file-name)
                    235:                    ;; file-exists-p is not the right thing above, as that
                    236:                    ;;  returns t iff the file is READABLE by you
                    237:                    "File exists, but is read-protected.")
                    238:                   ((file-attributes default-directory)
                    239:                    "File not found and directory write-protected")
                    240:                   (t
                    241:                    "File not found and directory doesn't exist")))
                    242:     (if auto-save-default
                    243:        (auto-save-mode t)))
                    244:   (normal-mode))
                    245: 
                    246: (defun normal-mode ()
                    247:   "Choose the major mode for this buffer automatically.
                    248: Also sets up any specified local variables of the file.
                    249: Uses the visited file name, the -*- line, and the local variables spec.
                    250: Finishes by calling value of find-file-hook if that's not nil."
                    251:   (interactive)
                    252:   (condition-case err
                    253:                  (set-auto-mode)
                    254:     (error (message "Error processing file's mode specifications: %s"
                    255:                    (prin1-to-string err))))
                    256:   (condition-case err
                    257:                  (hack-local-variables)
                    258:     (error (message "Error processing file's local variables: %s"
                    259:                    (prin1-to-string err))))
                    260:   (and find-file-hook
                    261:        (funcall find-file-hook)))
                    262: 
                    263: ;(defvar auto-mode-alist ...) now in loaddefs.el
                    264: (defun set-auto-mode ()
                    265:   "Select major mode appropriate for current buffer.
                    266: May base decision on visited file name (See variable  auto-mode-list)
                    267: or on buffer contents (-*- line or local variables spec), but does not look
                    268: for the \"mode:\" local variable. For that, use  hack-local-variables."
                    269:   ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
                    270:   (let (beg end mode)
                    271:     (save-excursion
                    272:       (goto-char (point-min))
                    273:       (skip-chars-forward " \t\n")
                    274:       (if (and (search-forward "-*-" (save-excursion (end-of-line) (point)) t)
                    275:               (progn
                    276:                 (skip-chars-forward " \t")
                    277:                 (setq beg (point))
                    278:                 (search-forward "-*-" (save-excursion (end-of-line) (point)) t))
                    279:               (progn
                    280:                 (forward-char -3)
                    281:                 (skip-chars-backward " \t")
                    282:                 (setq end (point))
                    283:                 (goto-char beg)
                    284:                 (if (search-forward ":" end t)
                    285:                     (progn
                    286:                       (goto-char beg)
                    287:                       (if (let ((case-fold-search t))
                    288:                             (search-forward "mode:" end t))
                    289:                           (progn
                    290:                             (skip-chars-forward " \t")
                    291:                             (setq beg (point))
                    292:                             (if (search-forward ";" end t)
                    293:                                 (forward-char -1)
                    294:                               (goto-char end))
                    295:                             (skip-chars-backward " \t")
                    296:                             (setq mode (buffer-substring beg (point))))))
                    297:                   (setq mode (buffer-substring beg end)))))
                    298:          (funcall (intern (concat (downcase mode) "-mode")))
                    299:        (let ((alist auto-mode-alist)
                    300:              (name buffer-file-name))
                    301:          (let (case-fold-search)
                    302:            ;; Remove backup-suffixes from file name.
                    303:            (setq name (substring name 0
                    304:                                  (or (string-match "\\.~[0-9]+~\\'" name)
                    305:                                      (string-match "~\\'" name)
                    306:                                      (length name))))
                    307:            ;; Find first matching alist entry.
                    308:            (while (and (not mode) alist)
                    309:              (if (string-match (car (car alist)) name)
                    310:                  (setq mode (cdr (car alist))))
                    311:              (setq alist (cdr alist))))
                    312:          (if mode (funcall mode)))))))
                    313: 
                    314: (defun hack-local-variables ()
                    315:   "Parse, and bind or evaluate as appropriate, any local variables
                    316: for current buffer."
                    317:   ;; Look for "Local variables:" line in last page.
                    318:   (save-excursion
                    319:     (goto-char (point-max))
                    320:     (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
                    321:     (if (let ((case-fold-search t))
                    322:          (search-forward "Local Variables:" nil t))
                    323:        (let ((continue t)
                    324:              prefix prefixlen suffix beg)
                    325:          ;; The prefix is what comes before "local variables:" in its line.
                    326:          ;; The suffix is what comes after "local variables:" in its line.
                    327:          (or (eolp)
                    328:              (setq suffix (buffer-substring (point)
                    329:                                             (progn (end-of-line) (point)))))
                    330:          (goto-char (match-beginning 0))
                    331:          (or (bolp)
                    332:              (setq prefix
                    333:                    (buffer-substring (point)
                    334:                                      (progn (beginning-of-line) (point)))))
                    335:          (if prefix (setq prefixlen (length prefix)
                    336:                           prefix (regexp-quote prefix)))
                    337:          (if suffix (setq suffix (regexp-quote suffix)))
                    338:          (while continue
                    339:            ;; Look at next local variable spec.
                    340:            (forward-line 1)
                    341:            ;; Skip the prefix, if any.
                    342:            (if prefix
                    343:                (if (looking-at prefix)
                    344:                    (forward-char prefixlen)
                    345:                  (error "Local variables entry is missing the prefix")))
                    346:            ;; Find the variable name; strip whitespace.
                    347:            (skip-chars-forward " \t")
                    348:            (setq beg (point))
                    349:            (skip-chars-forward "^:\n")
                    350:            (if (eolp) (error "Missing colon in local variables entry"))
                    351:            (skip-chars-backward " \t")
                    352:            (let* ((str (buffer-substring beg (point)))
                    353:                   (var (read str))
                    354:                  val)
                    355:              ;; Setting variable named "end" means end of list.
                    356:              (if (string-equal (downcase str) "end")
                    357:                  (setq continue nil)
                    358:                ;; Otherwise read the variable value.
                    359:                (skip-chars-forward "^:")
                    360:                (forward-char 1)
                    361:                (setq val (read (current-buffer)))
                    362:                (skip-chars-backward "\n")
                    363:                (skip-chars-forward " \t")
                    364:                (or (if suffix (looking-at suffix) (eolp))
                    365:                    (error "Local variables entry is terminated incorrectly"))
                    366:                ;; Set the variable.  "Variables" mode and eval are funny.
                    367:                (cond ((eq var 'mode)
                    368:                       (funcall (intern (concat (downcase (symbol-name val))
                    369:                                                "-mode"))))
                    370:                      ((eq var 'eval)
                    371:                       (eval val))
                    372:                      (t (make-local-variable var)
                    373:                         (set var val))))))))))
                    374: 
                    375: (defun set-visited-file-name (filename)
                    376:   "Change name of file visited in current buffer to FILENAME.
                    377: The next time the buffer is saved it will go in the newly specified file.
                    378: nil or empty string as argument means make buffer not be visiting any file."
                    379:   (interactive "FSet visited file name: ")
                    380:   (if filename
                    381:       (setq filename
                    382:            (if (string-equal filename "")
                    383:                nil
                    384:              (expand-file-name filename))))
                    385:   (or (equal filename buffer-file-name)
                    386:       (null filename)
                    387:       (progn
                    388:        (lock-buffer filename)
                    389:        (unlock-buffer)))
                    390:   (setq buffer-file-name filename)
                    391:   (if filename
                    392:       (progn
                    393:        (setq default-directory (file-name-directory buffer-file-name))
                    394:        (or (get-buffer (file-name-nondirectory buffer-file-name))
                    395:           (rename-buffer (file-name-nondirectory buffer-file-name)))))
                    396:   (setq buffer-backed-up nil)
                    397:   (clear-visited-file-modtime)
                    398:   (auto-save-mode (and buffer-file-name auto-save-default))
                    399:   (if buffer-file-name
                    400:       (set-buffer-modified-p t)))
                    401: 
                    402: (defun write-file (filename)
                    403:   "Write current buffer into file FILENAME.
                    404: Makes buffer visit that file, and marks it not modified."
                    405:   (interactive "FWrite file: ")
                    406:   (or (null filename) (string-equal filename "")
                    407:       (set-visited-file-name filename))
                    408:   (set-buffer-modified-p t)
                    409:   (save-buffer))
                    410: 
                    411: (defun backup-buffer ()
                    412:   "Make a backup of the disk file visited by the current buffer.
                    413: This is done before saving the buffer the first time."
                    414:   (and make-backup-files
                    415:        (not buffer-backed-up)
                    416:        (file-exists-p buffer-file-name)
                    417:        (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
                    418:             '(?- ?l))
                    419:        (or (< (length buffer-file-name) 5)
                    420:           (not (string-equal "/tmp/" (substring buffer-file-name 0 5))))
                    421:     (condition-case ()
                    422:        (let* ((backup-info (find-backup-file-name buffer-file-name))
                    423:               (backupname (car backup-info))
                    424:               (targets (cdr backup-info))
                    425:               setmodes)
                    426: ;        (if (file-directory-p buffer-file-name)
                    427: ;            (error "Cannot save buffer in directory %s" buffer-file-name))
                    428:          (if (or (file-symlink-p buffer-file-name)
                    429:                  backup-by-copying
                    430:                  (and backup-by-copying-when-linked
                    431:                       (> (file-nlinks buffer-file-name) 1)))
                    432:              (copy-file buffer-file-name backupname t)
                    433:            (condition-case ()
                    434:                (delete-file backupname)
                    435:              (file-error nil))
                    436:            (rename-file buffer-file-name backupname t)
                    437:            (setq setmodes (file-modes backupname)))
                    438:          (setq buffer-backed-up t)
                    439:          (if (and targets
                    440:                   (or trim-versions-without-asking
                    441:                       (y-or-n-p (format "Delete excess backup versions of %s? "
                    442:                                         buffer-file-name))))
                    443:              (while targets
                    444:                (condition-case ()
                    445:                    (delete-file (car targets))
                    446:                  (file-error nil))
                    447:                (setq targets (cdr targets))))
                    448:          setmodes)
                    449:       (file-error nil))))
                    450: 
                    451: (defun find-backup-file-name (fn)
                    452:   "Find a file name for a backup file, and suggestions for deletions.
                    453: Value is a list whose car is the name for the backup file
                    454:  and whose cdr is a list of old versions to consider deleting now."
                    455:   (if (eq version-control 'never)
                    456:       (list (concat fn "~"))
                    457:     (let* ((base-versions (concat (file-name-nondirectory fn) ".~"))
                    458:           (bv-length (length base-versions))
                    459:           (possibilities (file-name-all-completions
                    460:                           base-versions
                    461:                           (file-name-directory fn)))
                    462:           (versions (sort (mapcar 'backup-extract-version possibilities)
                    463:                           '<))
                    464:           (high-water-mark (apply 'max (cons 0 versions)))
                    465:           (deserve-versions-p
                    466:            (or version-control
                    467:                (> high-water-mark 0)))
                    468:           (number-to-delete (- (length versions)
                    469:                                kept-old-versions kept-new-versions -1)))
                    470:       (if (not deserve-versions-p)
                    471:          (list (concat fn "~"))
                    472:        (cons (concat fn ".~" (int-to-string (1+ high-water-mark)) "~")
                    473:              (if (> number-to-delete 0)
                    474:                  (mapcar (function (lambda (n)
                    475:                                      (concat fn ".~" (int-to-string n) "~")))
                    476:                          (let ((v (nthcdr kept-old-versions versions)))
                    477:                            (rplacd (nthcdr (1- number-to-delete) v) ())
                    478:                            v))))))))
                    479: 
                    480: (defun backup-extract-version (fn)
                    481:   (string-to-int (substring fn bv-length -1)))
                    482: 
                    483: (defun file-nlinks (filename)
                    484:   "Return number of names file FILENAME has." 
                    485:   (car (cdr (file-attributes filename))))
                    486: 
                    487: (defun save-buffer (&optional args)
                    488:   "Save current buffer in visited file if modified.  Versions described below.
                    489: 
                    490: With no arg, only backs up if first save or previously motivated.
                    491: With 1 or 3 \\[universal-argument]'s, marks this version to be backed up.
                    492: With 2 or 3 \\[universal-argument]'s, unconditionally backs up previous \
                    493: version.
                    494: 
                    495: If a file's name is FOO, the names of numbered versions are
                    496:  FOO.~i~ for various integers i.
                    497: Numeric backups (rather than FOO~) will be made if value of
                    498:  version-control  is not the atom never and either there are already
                    499:  numeric versions of the file being backed up, or  version-control  is
                    500:  non-nil.
                    501: dired-kept-versions  controls dired's clean-directory (.) command.
                    502: We don't want excessive versions piling up, so variables
                    503:  kept-old-versions , which tells system how many oldest versions to
                    504:  keep, and  kept-new-versions , which tells how many new versions to
                    505:  keep, are provided.  Defaults are 2 old versions and 2 new.
                    506: If  trim-versions-without-asking  is nil, system will query user
                    507:  before trimming versions.  Otherwise it does it silently."
                    508:   (interactive "p")
                    509:   (let ((modp (buffer-modified-p)))
                    510:     (and modp (memq args '(4 64)) (setq buffer-backed-up nil))
                    511:     (basic-save-buffer)
                    512:     (and modp (memq args '(16 64)) (setq buffer-backed-up nil))))
                    513: 
                    514: (defun delete-auto-save-file-if-necessary ()
                    515:   "Delete the auto-save filename for the current buffer (if it has one)
                    516: if variable  delete-auto-save-files  is non-nil."
                    517:   (and buffer-auto-save-file-name delete-auto-save-files
                    518:        (progn
                    519:         (condition-case ()
                    520:             (delete-file buffer-auto-save-file-name)
                    521:           (file-error nil))
                    522:         (set-buffer-auto-saved))))
                    523: 
                    524: (defun basic-save-buffer ()
                    525:   "Save the current buffer in its visited file, if it has been modified."  
                    526:   (interactive)
                    527:   (if (buffer-modified-p)
                    528:       (let (setmodes tempsetmodes)
                    529:        (or buffer-file-name
                    530:            (setq buffer-file-name
                    531:                  (expand-file-name (read-file-name "File to save in: ") nil)
                    532:                  default-directory (file-name-directory buffer-file-name)))
                    533:        (if (not (file-writable-p buffer-file-name))
                    534:            (if (yes-or-no-p
                    535:                 (format "File %s is write-protected; try to save anyway? "
                    536:                         (file-name-nondirectory buffer-file-name)))
                    537:                (setq tempsetmodes t)
                    538:              (error
                    539:    "Attempt to save to a file which you aren't allowed to write")))
                    540:        (or (verify-visited-file-modtime (current-buffer))
                    541:            (not (file-exists-p buffer-file-name))
                    542:            (yes-or-no-p
                    543:              "File has changed on disk since last visited or saved.  Save anyway? ")
                    544:            (error "Save not confirmed"))
                    545:        (or buffer-backed-up
                    546:            (setq setmodes (backup-buffer)))
                    547:        (save-restriction
                    548:          (widen)
                    549:          (and (> (point-max) 1)
                    550:               (/= (char-after (1- (point-max))) ?\n)
                    551:               (or (eq require-final-newline t)
                    552:                   (and require-final-newline
                    553:                        (yes-or-no-p
                    554:                         (format "Buffer %s does not end in newline.  Add one? "
                    555:                                 (buffer-name)))))
                    556:               (save-excursion
                    557:                 (goto-char (point-max))
                    558:                 (insert ?\n)))
                    559:          (and write-file-hook
                    560:               (funcall write-file-hook))
                    561:          ;; If file not writable, see if we can make it writable
                    562:          ;; temporarily while we write it.
                    563:          ;; But no need to do so if we have just backed up the file
                    564:          ;; (if setmodes is set) because in that case we are superseding.
                    565:          (cond ((and tempsetmodes (not setmodes))
                    566:                 ;; Change the mode back, after writing.
                    567:                 (setq setmodes (file-modes buffer-file-name))
                    568:                 (set-file-modes buffer-file-name 511)))
                    569:          (write-region (point-min) (point-max) buffer-file-name nil t)
                    570:          (if setmodes
                    571:              (condition-case ()
                    572:                   (set-file-modes buffer-file-name setmodes)
                    573:                (error nil))))
                    574:        (delete-auto-save-file-if-necessary))
                    575:     (message "(No changes need to be saved)")))
                    576: 
                    577: (defun save-some-buffers (&optional arg)
                    578:   "Save some modified file-visiting buffers.  Asks user about each one.
                    579: With argument, saves all with no questions."
                    580:   (interactive "P")
                    581:   (let (considered (list (buffer-list)))
                    582:     (while list
                    583:       (let ((buffer (car list)))
                    584:        (condition-case ()
                    585:            (and (buffer-modified-p buffer)
                    586:                 (buffer-file-name buffer)
                    587:                 (setq considered t)
                    588:                 (or arg
                    589:                     (y-or-n-p (format "Save file %s? " (buffer-file-name buffer))))
                    590:                 (save-excursion
                    591:                   (set-buffer buffer)
                    592:                   (save-buffer)))
                    593:          (error nil)))
                    594:       (setq list (cdr list)))
                    595:     (and save-abbrevs abbrevs-changed
                    596:         (setq considered t)
                    597:         (or arg
                    598:             (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
                    599:         (progn
                    600:          (write-abbrev-file nil)
                    601:          (setq abbrevs-changed nil)))
                    602:     (if considered
                    603:        (message "")
                    604:        (message "(No files need saving)"))))
                    605: 
                    606: (defun not-modified ()
                    607:   "Mark current buffer as unmodified, not needing to be saved."
                    608:   (interactive)
                    609:   (message "Modification-flag cleared")
                    610:   (set-buffer-modified-p nil))
                    611: 
                    612: (defun toggle-read-only ()
                    613:   "Change whether this buffer is visiting its file read-only."
                    614:   (interactive)
                    615:   (setq buffer-read-only (not buffer-read-only))
                    616:   ;; Force mode-line redisplay
                    617:   (set-buffer-modified-p (buffer-modified-p)))
                    618: 
                    619: (defun insert-file (filename)
                    620:   "Insert contents of file FILENAME into buffer after point.
                    621: Set mark after the inserted text."
                    622:   (interactive "fInsert file: ")
                    623:   (let ((tem (insert-file-contents filename)))
                    624:     (push-mark (+ (point) (car (cdr tem))))))
                    625: 
                    626: (defun append-to-file (start end filename)
                    627:   "Append the contents of the region to the end of file FILENAME.
                    628: When called from a function, expects three arguments,
                    629: START, END and FILENAME.  START and END are buffer positions
                    630: saying what text to write."
                    631:   (interactive "r\nFAppend to file: ")
                    632:   (write-region start end filename t))
                    633: 
                    634: (defvar revert-buffer-function nil
                    635:   "Function to use to revert this buffer, or nil to do the default.")
                    636: 
                    637: (defun revert-buffer (&optional arg)
                    638:   "Replace the buffer text with the text of the visited file on disk.
                    639: This undoes all changes since the file was visited or saved.
                    640: If latest auto-save file is more recent than the visited file,
                    641: asks user whether to use that instead, unless a non-nil argument is given.
                    642: 
                    643: If revert-buffer-function's value is non-nil, it is called to do the work."
                    644:   (interactive "P")
                    645:   (if revert-buffer-function
                    646:       (funcall revert-buffer-function arg)
                    647:     (let* ((opoint (point))
                    648:           (auto-save-p (and (null arg) (recent-auto-save-p)
                    649:                             (y-or-n-p
                    650:    "Buffer has been auto-saved recently.  Revert from auto-save file? ")))
                    651:           (file-name (if auto-save-p
                    652:                          buffer-auto-save-file-name
                    653:                        buffer-file-name)))
                    654:       (cond ((null file-name)
                    655:             (error "Buffer does not seem to be associated with any file"))
                    656:            ((not (file-exists-p file-name))
                    657:             (error "File %s no longer exists!" file-name))
                    658:            ((yes-or-no-p (format "Revert buffer from file %s? " file-name))
                    659:             (let ((buffer-read-only nil))
                    660:               ;; Bind buffer-file-name to nil
                    661:               ;; so that we don't try to lock the file.
                    662:               (let ((buffer-file-name nil))
                    663:                 (or auto-save-p
                    664:                     (unlock-buffer))
                    665:                 (erase-buffer))
                    666:               (insert-file-contents file-name (not auto-save-p)))
                    667:             (after-find-file nil)
                    668:             (or find-file-hook         ; the hook may have set point itself
                    669:                 (goto-char (min opoint (point-max)))))))))
                    670: 
                    671: (defun recover-file (file)
                    672:   "Visit file FILE, then get contents from its last auto-save file."
                    673:   (interactive "FRecover file: ")
                    674:   (find-file file)
                    675:   (let ((file-name (make-auto-save-file-name)))
                    676:     (cond ((not (file-exists-p file-name))
                    677:           (error "Auto-save file %s does not exist" file-name))
                    678:          ((yes-or-no-p (format "Recover buffer from file %s? " file-name))
                    679:           (let ((buffer-read-only nil))
                    680:             (erase-buffer)
                    681:             (insert-file-contents file-name nil))
                    682:           (after-find-file nil))))
                    683:   (setq buffer-auto-save-file-name nil)
                    684:   (message "Auto-save turned off, for now, in this buffer"))
                    685: 
                    686: (defun kill-some-buffers ()
                    687:   "For each buffer, ask whether to kill it."
                    688:   (interactive)
                    689:   (let ((list (buffer-list)))
                    690:     (while list
                    691:       (let* ((buffer (car list))
                    692:             (name (buffer-name buffer)))
                    693:        (and (not (string-equal name ""))
                    694:             (/= (aref name 0) ? )
                    695:             (yes-or-no-p
                    696:              (format "Buffer %s %s.  Kill? "
                    697:                      name
                    698:                      (if (buffer-modified-p buffer)
                    699:                          "HAS BEEN EDITED" "is unmodified")))
                    700:             (kill-buffer buffer)))
                    701:       (setq list (cdr list)))))
                    702: 
                    703: (defun auto-save-mode (arg)
                    704:   "Toggle auto-saving of contents of current buffer.
                    705: With arg, turn auto-saving on if arg is positive, else off."
                    706:   (interactive "P")
                    707:   (setq buffer-auto-save-file-name
                    708:         (and (if (null arg)
                    709:                 (not buffer-auto-save-file-name)
                    710:               (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))
                    711:             (if (and buffer-file-name auto-save-visited-file-name
                    712:                      (not buffer-read-only))
                    713:                 buffer-file-name
                    714:               (make-auto-save-file-name)))))
                    715: 
                    716: (defun make-auto-save-file-name ()
                    717:   "Return file name to use for auto-saves of current buffer.
                    718: Does not consider auto-save-visited-file-name; that is checked
                    719: before calling this function.
                    720: This is a separate function so your .emacs file or site-init.el can redefine it.
                    721: See also auto-save-file-name-p."
                    722:   (if buffer-file-name
                    723:       (concat (file-name-directory buffer-file-name)
                    724:              "#"
                    725:              (file-name-nondirectory buffer-file-name))
                    726:     (expand-file-name (concat "#%" (buffer-name)))))
                    727: 
                    728: (defun auto-save-file-name-p (filename)
                    729:   "Return t if FILENAME can be yielded by make-auto-save-file-name.
                    730: FILENAME should lack slashes.
                    731: This is a separate function so your .emacs file or site-init.el can redefine it."
                    732:   (string-match "^#" filename))
                    733: 
                    734: (defconst list-directory-brief-switches "-CF"
                    735:   "*Switches for list-directory to pass to `ls' for brief listing,")
                    736: (defconst list-directory-verbose-switches "-l"
                    737:   "*Switches for list-directory to pass to `ls' for verbose listing,")
                    738: 
                    739: (defun list-directory (dirname &optional verbose)
                    740:   "Display a list of files in or matching DIRNAME, a la `ls'.
                    741: DIRNAME is globbed by the shell if necessary.
                    742: Prefix arg (second arg if noninteractive) means supply -l switch to `ls'.
                    743: Actions controlled by variables list-directory-brief-switches
                    744:  and list-directory-verbose-switches."
                    745:   (interactive (let ((pfx current-prefix-arg))
                    746:                 (list (read-file-name (if pfx "List directory (verbose): "
                    747:                                         "List directory (brief): ")
                    748:                                       nil default-directory nil)
                    749:                       pfx)))
                    750:   (let ((switches (if verbose list-directory-verbose-switches
                    751:                    list-directory-brief-switches))
                    752:        full-dir-p)
                    753:     (or dirname (setq dirname default-directory))
                    754:     (if (file-directory-p dirname)
                    755:        (progn
                    756:         (setq full-dir-p t)
                    757:         (or (string-match "/$" dirname)
                    758:             (setq dirname (concat dirname "/")))))
                    759:     (setq dirname (expand-file-name dirname))
                    760:     (with-output-to-temp-buffer "*Directory*"
                    761:       (buffer-flush-undo standard-output)
                    762:       (princ "Directory ")
                    763:       (princ dirname)
                    764:       (terpri)
                    765:       (if full-dir-p
                    766:          (call-process "/bin/ls" nil standard-output nil
                    767:                        switches dirname)
                    768:        (let ((default-directory (file-name-directory dirname)))
                    769:          (call-process shell-file-name nil standard-output nil
                    770:                        "-c" (concat "exec /bin/ls "
                    771:                                     switches " "
                    772:                                     (file-name-nondirectory dirname))))))))
                    773: 
                    774: (defun save-buffers-kill-emacs ()
                    775:   "Offer to save each buffer, then kill this Emacs fork."
                    776:   (interactive)
                    777:   (save-some-buffers)
                    778:   (kill-emacs))
                    779: 
                    780: (define-key ctl-x-map "\C-f" 'find-file)
                    781: (define-key ctl-x-map "\C-q" 'toggle-read-only)
                    782: (define-key ctl-x-map "\C-r" 'find-file-read-only)
                    783: (define-key ctl-x-map "\C-v" 'find-alternate-file)
                    784: (define-key ctl-x-map "\C-s" 'save-buffer)
                    785: (define-key ctl-x-map "s" 'save-some-buffers)
                    786: (define-key ctl-x-map "\C-w" 'write-file)
                    787: (define-key ctl-x-map "i" 'insert-file)
                    788: (define-key esc-map "~" 'not-modified)
                    789: (define-key ctl-x-map "\C-d" 'list-directory)
                    790: (define-key ctl-x-map "\C-c" 'save-buffers-kill-emacs)
                    791: 
                    792: (defvar ctl-x-4-map (make-keymap)
                    793:   "Keymap for subcommands of C-x 4")
                    794: (fset 'ctl-x-4-prefix ctl-x-4-map)
                    795: (define-key ctl-x-map "4" 'ctl-x-4-prefix)
                    796: (define-key ctl-x-4-map "f" 'find-file-other-window)
                    797: (define-key ctl-x-4-map "\C-f" 'find-file-other-window)
                    798: (define-key ctl-x-4-map "b" 'switch-to-buffer-other-window)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.