2009-08-12 20:29:30 +00:00
|
|
|
|
;;; files-x.el --- extended file handling commands
|
|
|
|
|
|
2020-01-01 00:19:43 +00:00
|
|
|
|
;; Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;; Author: Juri Linkov <juri@jurta.org>
|
2019-05-25 20:43:06 +00:00
|
|
|
|
;; Maintainer: emacs-devel@gnu.org
|
2009-08-12 20:29:30 +00:00
|
|
|
|
;; Keywords: files
|
2010-08-29 16:17:13 +00:00
|
|
|
|
;; Package: emacs
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;; 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
|
2017-09-13 22:52:52 +00:00
|
|
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;; This file defines additional infrequently used file- and
|
|
|
|
|
;; directory-handling commands that should not be in files.el
|
|
|
|
|
;; to not make the dumped image bigger.
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2018-11-07 22:27:58 +00:00
|
|
|
|
(eval-when-compile (require 'subr-x)) ; for string-trim-right
|
|
|
|
|
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;; Commands to add/delete file-local/directory-local variables.
|
|
|
|
|
|
|
|
|
|
(defun read-file-local-variable (prompt)
|
|
|
|
|
"Read file-local variable using PROMPT and completion.
|
|
|
|
|
Intended to be used in the `interactive' spec of
|
|
|
|
|
`add-file-local-variable', `delete-file-local-variable',
|
|
|
|
|
`add-dir-local-variable', `delete-dir-local-variable'."
|
2013-06-25 13:07:04 +00:00
|
|
|
|
(let* ((default (variable-at-point))
|
|
|
|
|
(default (and (symbolp default) (boundp default)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(symbol-name default)))
|
2013-06-25 13:07:04 +00:00
|
|
|
|
(variable
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(completing-read
|
|
|
|
|
(if default
|
|
|
|
|
(format "%s (default %s): " prompt default)
|
|
|
|
|
(format "%s: " prompt))
|
|
|
|
|
obarray
|
|
|
|
|
(lambda (sym)
|
2012-04-09 12:36:01 +00:00
|
|
|
|
(or (custom-variable-p sym)
|
2009-10-07 14:33:31 +00:00
|
|
|
|
(get sym 'safe-local-variable)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(memq sym '(mode eval coding unibyte))))
|
2013-06-25 13:07:04 +00:00
|
|
|
|
nil nil nil default nil)))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(and (stringp variable) (intern variable))))
|
|
|
|
|
|
|
|
|
|
(defun read-file-local-variable-value (variable)
|
|
|
|
|
"Read value of file-local VARIABLE using completion.
|
|
|
|
|
Intended to be used in the `interactive' spec of
|
|
|
|
|
`add-file-local-variable' and `add-dir-local-variable'."
|
2013-06-25 13:07:04 +00:00
|
|
|
|
(cond
|
|
|
|
|
((eq variable 'mode)
|
|
|
|
|
(let* ((default (and (symbolp major-mode) (symbol-name major-mode)))
|
|
|
|
|
(value
|
|
|
|
|
(completing-read
|
|
|
|
|
(if default
|
|
|
|
|
(format "Add %s with value (default %s): " variable default)
|
|
|
|
|
(format "Add %s with value: " variable))
|
|
|
|
|
obarray
|
|
|
|
|
(lambda (sym)
|
|
|
|
|
(string-match-p "-mode\\'" (symbol-name sym)))
|
|
|
|
|
nil nil nil default nil)))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(and (stringp value)
|
2013-06-25 13:07:04 +00:00
|
|
|
|
(intern (replace-regexp-in-string "-mode\\'" "" value)))))
|
|
|
|
|
((eq variable 'eval)
|
|
|
|
|
(read--expression (format "Add %s with expression: " variable)))
|
|
|
|
|
((eq variable 'coding)
|
|
|
|
|
(let ((default (and (symbolp buffer-file-coding-system)
|
|
|
|
|
(symbol-name buffer-file-coding-system))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(read-coding-system
|
|
|
|
|
(if default
|
2013-06-25 13:07:04 +00:00
|
|
|
|
(format "Add %s with value (default %s): " variable default)
|
|
|
|
|
(format "Add %s with value: " variable))
|
|
|
|
|
default)))
|
|
|
|
|
(t
|
|
|
|
|
(let ((default (format "%S"
|
|
|
|
|
(cond ((eq variable 'unibyte) t)
|
|
|
|
|
((boundp variable)
|
|
|
|
|
(symbol-value variable)))))
|
|
|
|
|
(minibuffer-completing-symbol t))
|
|
|
|
|
(read-from-minibuffer (format "Add %s with value: " variable)
|
|
|
|
|
nil read-expression-map t
|
2013-06-25 20:48:54 +00:00
|
|
|
|
'set-variable-value-history
|
|
|
|
|
default)))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
(defun read-file-local-variable-mode ()
|
|
|
|
|
"Read per-directory file-local variable's mode using completion.
|
|
|
|
|
Intended to be used in the `interactive' spec of
|
|
|
|
|
`add-dir-local-variable', `delete-dir-local-variable'."
|
|
|
|
|
(let* ((default (and (symbolp major-mode) (symbol-name major-mode)))
|
|
|
|
|
(mode
|
|
|
|
|
(completing-read
|
|
|
|
|
(if default
|
|
|
|
|
(format "Mode or subdirectory (default %s): " default)
|
|
|
|
|
(format "Mode or subdirectory: "))
|
|
|
|
|
obarray
|
|
|
|
|
(lambda (sym)
|
|
|
|
|
(and (string-match-p "-mode\\'" (symbol-name sym))
|
2013-06-25 13:07:04 +00:00
|
|
|
|
(not (or (memq sym minor-mode-list)
|
|
|
|
|
(string-match-p "-minor-mode\\'"
|
|
|
|
|
(symbol-name sym))))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
nil nil nil default nil)))
|
|
|
|
|
(cond
|
|
|
|
|
((equal mode "nil") nil)
|
|
|
|
|
((and (stringp mode) (fboundp (intern mode))) (intern mode))
|
|
|
|
|
(t mode))))
|
|
|
|
|
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(defun modify-file-local-variable-message (variable value op)
|
|
|
|
|
(let* ((not-value (make-symbol ""))
|
|
|
|
|
(old-value (cond ((eq variable 'mode)
|
|
|
|
|
major-mode)
|
|
|
|
|
((eq variable 'coding)
|
|
|
|
|
buffer-file-coding-system)
|
|
|
|
|
(t (if (and (symbolp variable)
|
|
|
|
|
(boundp variable))
|
|
|
|
|
(symbol-value variable)
|
|
|
|
|
not-value))))
|
|
|
|
|
(new-value (if (eq op 'delete)
|
|
|
|
|
(cond ((eq variable 'mode)
|
|
|
|
|
(default-value 'major-mode))
|
|
|
|
|
((eq variable 'coding)
|
|
|
|
|
(default-value 'buffer-file-coding-system))
|
|
|
|
|
(t (if (and (symbolp variable)
|
|
|
|
|
(default-boundp variable))
|
|
|
|
|
(default-value variable)
|
|
|
|
|
not-value)))
|
|
|
|
|
(cond ((eq variable 'mode)
|
|
|
|
|
(let ((string (format "%S" value)))
|
|
|
|
|
(if (string-match-p "-mode\\'" string)
|
|
|
|
|
value
|
|
|
|
|
(intern (concat string "-mode")))))
|
|
|
|
|
(t value)))))
|
|
|
|
|
(when (or (eq old-value not-value)
|
|
|
|
|
(eq new-value not-value)
|
|
|
|
|
(not (equal old-value new-value)))
|
|
|
|
|
(message "%s" (substitute-command-keys
|
|
|
|
|
"For this change to take effect revisit file using \\[revert-buffer]")))))
|
|
|
|
|
|
|
|
|
|
(defun modify-file-local-variable (variable value op &optional interactive)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
"Modify file-local VARIABLE in Local Variables depending on operation OP.
|
|
|
|
|
|
|
|
|
|
If OP is `add-or-replace' then delete all existing settings of
|
|
|
|
|
VARIABLE (except `mode' and `eval') and add a new file-local VARIABLE
|
|
|
|
|
with VALUE to the Local Variables list.
|
|
|
|
|
|
|
|
|
|
If there is no Local Variables list in the current file buffer and OP
|
|
|
|
|
is not `delete' then this function adds the first line containing the
|
|
|
|
|
string `Local Variables:' and the last line containing the string `End:'.
|
|
|
|
|
|
|
|
|
|
If OP is `delete' then delete all existing settings of VARIABLE
|
|
|
|
|
from the Local Variables list ignoring the input argument VALUE."
|
|
|
|
|
(catch 'exit
|
|
|
|
|
(let ((beg (point)) end replaced-pos)
|
|
|
|
|
(unless enable-local-variables
|
|
|
|
|
(throw 'exit (message "File-local variables are disabled")))
|
|
|
|
|
|
|
|
|
|
;; Look for "Local variables:" line in last page.
|
|
|
|
|
(widen)
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
|
|
|
|
|
|
|
|
|
|
;; Add "Local variables:" list if not found.
|
|
|
|
|
(unless (let ((case-fold-search t))
|
|
|
|
|
(search-forward "Local Variables:" nil t))
|
|
|
|
|
|
|
|
|
|
;; Don't add "Local variables:" list for the deletion operation.
|
|
|
|
|
(when (eq op 'delete)
|
|
|
|
|
(throw 'exit (progn (goto-char beg)
|
|
|
|
|
(message "Local Variables not found"))))
|
|
|
|
|
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(let ((comment-style 'plain)
|
2011-11-18 14:34:39 +00:00
|
|
|
|
(comment-start (or comment-start ";; ")))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(comment-region
|
|
|
|
|
(prog1 (setq beg (point))
|
|
|
|
|
(insert "\nLocal Variables:\nEnd:\n"))
|
|
|
|
|
(point)))
|
|
|
|
|
|
|
|
|
|
(unless (let ((case-fold-search t))
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(search-forward "Local Variables:" nil t))
|
Go back to grave quoting in source-code docstrings etc.
This reverts almost all my recent changes to use curved quotes
in docstrings and/or strings used for error diagnostics.
There are a few exceptions, e.g., Bahá’í proper names.
* admin/unidata/unidata-gen.el (unidata-gen-table):
* lisp/abbrev.el (expand-region-abbrevs):
* lisp/align.el (align-region):
* lisp/allout.el (allout-mode, allout-solicit-alternate-bullet)
(outlineify-sticky):
* lisp/apropos.el (apropos-library):
* lisp/bookmark.el (bookmark-default-annotation-text):
* lisp/button.el (button-category-symbol, button-put)
(make-text-button):
* lisp/calc/calc-aent.el (math-read-if, math-read-factor):
* lisp/calc/calc-embed.el (calc-do-embedded):
* lisp/calc/calc-ext.el (calc-user-function-list):
* lisp/calc/calc-graph.el (calc-graph-show-dumb):
* lisp/calc/calc-help.el (calc-describe-key)
(calc-describe-thing, calc-full-help):
* lisp/calc/calc-lang.el (calc-c-language)
(math-parse-fortran-vector-end, math-parse-tex-sum)
(math-parse-eqn-matrix, math-parse-eqn-prime)
(calc-yacas-language, calc-maxima-language, calc-giac-language)
(math-read-giac-subscr, math-read-math-subscr)
(math-read-big-rec, math-read-big-balance):
* lisp/calc/calc-misc.el (calc-help, report-calc-bug):
* lisp/calc/calc-mode.el (calc-auto-why, calc-save-modes)
(calc-auto-recompute):
* lisp/calc/calc-prog.el (calc-fix-token-name)
(calc-read-parse-table-part, calc-user-define-invocation)
(math-do-arg-check):
* lisp/calc/calc-store.el (calc-edit-variable):
* lisp/calc/calc-units.el (math-build-units-table-buffer):
* lisp/calc/calc-vec.el (math-read-brackets):
* lisp/calc/calc-yank.el (calc-edit-mode):
* lisp/calc/calc.el (calc, calc-do, calc-user-invocation):
* lisp/calendar/appt.el (appt-display-message):
* lisp/calendar/diary-lib.el (diary-check-diary-file)
(diary-mail-entries, diary-from-outlook):
* lisp/calendar/icalendar.el (icalendar-export-region)
(icalendar--convert-float-to-ical)
(icalendar--convert-date-to-ical)
(icalendar--convert-ical-to-diary)
(icalendar--convert-recurring-to-diary)
(icalendar--add-diary-entry):
* lisp/calendar/time-date.el (format-seconds):
* lisp/calendar/timeclock.el (timeclock-mode-line-display)
(timeclock-make-hours-explicit, timeclock-log-data):
* lisp/calendar/todo-mode.el (todo-prefix, todo-delete-category)
(todo-item-mark, todo-check-format)
(todo-insert-item--next-param, todo-edit-item--next-key)
(todo-mode):
* lisp/cedet/ede/pmake.el (ede-proj-makefile-insert-dist-rules):
* lisp/cedet/mode-local.el (describe-mode-local-overload)
(mode-local-print-binding, mode-local-describe-bindings-2):
* lisp/cedet/semantic/complete.el (semantic-displayor-show-request):
* lisp/cedet/srecode/srt-mode.el (srecode-macro-help):
* lisp/cus-start.el (standard):
* lisp/cus-theme.el (describe-theme-1):
* lisp/custom.el (custom-add-dependencies, custom-check-theme)
(custom--sort-vars-1, load-theme):
* lisp/descr-text.el (describe-text-properties-1, describe-char):
* lisp/dired-x.el (dired-do-run-mail):
* lisp/dired.el (dired-log):
* lisp/emacs-lisp/advice.el (ad-read-advised-function)
(ad-read-advice-class, ad-read-advice-name, ad-enable-advice)
(ad-disable-advice, ad-remove-advice, ad-set-argument)
(ad-set-arguments, ad--defalias-fset, ad-activate)
(ad-deactivate):
* lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand)
(byte-compile-unfold-lambda, byte-optimize-form-code-walker)
(byte-optimize-while, byte-optimize-apply):
* lisp/emacs-lisp/byte-run.el (defun, defsubst):
* lisp/emacs-lisp/bytecomp.el (byte-compile-lapcode)
(byte-compile-log-file, byte-compile-format-warn)
(byte-compile-nogroup-warn, byte-compile-arglist-warn)
(byte-compile-cl-warn)
(byte-compile-warn-about-unresolved-functions)
(byte-compile-file, byte-compile--declare-var)
(byte-compile-file-form-defmumble, byte-compile-form)
(byte-compile-normal-call, byte-compile-check-variable)
(byte-compile-variable-ref, byte-compile-variable-set)
(byte-compile-subr-wrong-args, byte-compile-setq-default)
(byte-compile-negation-optimizer)
(byte-compile-condition-case--old)
(byte-compile-condition-case--new, byte-compile-save-excursion)
(byte-compile-defvar, byte-compile-autoload)
(byte-compile-lambda-form)
(byte-compile-make-variable-buffer-local, display-call-tree)
(batch-byte-compile):
* lisp/emacs-lisp/cconv.el (cconv-convert, cconv--analyze-use):
* lisp/emacs-lisp/chart.el (chart-space-usage):
* lisp/emacs-lisp/check-declare.el (check-declare-scan)
(check-declare-warn, check-declare-file)
(check-declare-directory):
* lisp/emacs-lisp/checkdoc.el (checkdoc-this-string-valid-engine)
(checkdoc-message-text-engine):
* lisp/emacs-lisp/cl-extra.el (cl-parse-integer)
(cl--describe-class):
* lisp/emacs-lisp/cl-generic.el (cl-defgeneric)
(cl--generic-describe, cl-generic-generalizers):
* lisp/emacs-lisp/cl-macs.el (cl--parse-loop-clause, cl-tagbody)
(cl-symbol-macrolet):
* lisp/emacs-lisp/cl.el (cl-unload-function, flet):
* lisp/emacs-lisp/copyright.el (copyright)
(copyright-update-directory):
* lisp/emacs-lisp/edebug.el (edebug-read-list):
* lisp/emacs-lisp/eieio-base.el (eieio-persistent-read):
* lisp/emacs-lisp/eieio-core.el (eieio--slot-override)
(eieio-oref):
* lisp/emacs-lisp/eieio-opt.el (eieio-help-constructor):
* lisp/emacs-lisp/eieio-speedbar.el:
(eieio-speedbar-child-make-tag-lines)
(eieio-speedbar-child-description):
* lisp/emacs-lisp/eieio.el (defclass, change-class):
* lisp/emacs-lisp/elint.el (elint-file, elint-get-top-forms)
(elint-init-form, elint-check-defalias-form)
(elint-check-let-form):
* lisp/emacs-lisp/ert.el (ert-get-test, ert-results-mode-menu)
(ert-results-pop-to-backtrace-for-test-at-point)
(ert-results-pop-to-messages-for-test-at-point)
(ert-results-pop-to-should-forms-for-test-at-point)
(ert-describe-test):
* lisp/emacs-lisp/find-func.el (find-function-search-for-symbol)
(find-function-library):
* lisp/emacs-lisp/generator.el (iter-yield):
* lisp/emacs-lisp/gv.el (gv-define-simple-setter):
* lisp/emacs-lisp/lisp-mnt.el (lm-verify):
* lisp/emacs-lisp/macroexp.el (macroexp--obsolete-warning):
* lisp/emacs-lisp/map-ynp.el (map-y-or-n-p):
* lisp/emacs-lisp/nadvice.el (advice--make-docstring)
(advice--make, define-advice):
* lisp/emacs-lisp/package-x.el (package-upload-file):
* lisp/emacs-lisp/package.el (package-version-join)
(package-disabled-p, package-activate-1, package-activate)
(package--download-one-archive)
(package--download-and-read-archives)
(package-compute-transaction, package-install-from-archive)
(package-install, package-install-selected-packages)
(package-delete, package-autoremove, describe-package-1)
(package-install-button-action, package-delete-button-action)
(package-menu-hide-package, package-menu--list-to-prompt)
(package-menu--perform-transaction)
(package-menu--find-and-notify-upgrades):
* lisp/emacs-lisp/pcase.el (pcase-exhaustive, pcase--u1):
* lisp/emacs-lisp/re-builder.el (reb-enter-subexp-mode):
* lisp/emacs-lisp/ring.el (ring-previous, ring-next):
* lisp/emacs-lisp/rx.el (rx-check, rx-anything)
(rx-check-any-string, rx-check-any, rx-check-not, rx-=)
(rx-repeat, rx-check-backref, rx-syntax, rx-check-category)
(rx-form):
* lisp/emacs-lisp/smie.el (smie-config-save):
* lisp/emacs-lisp/subr-x.el (internal--check-binding):
* lisp/emacs-lisp/tabulated-list.el (tabulated-list-put-tag):
* lisp/emacs-lisp/testcover.el (testcover-1value):
* lisp/emacs-lisp/timer.el (timer-event-handler):
* lisp/emulation/viper-cmd.el (viper-toggle-parse-sexp-ignore-comments)
(viper-toggle-search-style, viper-kill-buffer)
(viper-brac-function):
* lisp/emulation/viper-macs.el (viper-record-kbd-macro):
* lisp/env.el (setenv):
* lisp/erc/erc-button.el (erc-nick-popup):
* lisp/erc/erc.el (erc-cmd-LOAD, erc-handle-login, english):
* lisp/eshell/em-dirs.el (eshell/cd):
* lisp/eshell/em-glob.el (eshell-glob-regexp)
(eshell-glob-entries):
* lisp/eshell/em-pred.el (eshell-parse-modifiers):
* lisp/eshell/esh-opt.el (eshell-show-usage):
* lisp/facemenu.el (facemenu-add-new-face)
(facemenu-add-new-color):
* lisp/faces.el (read-face-name, read-face-font, describe-face)
(x-resolve-font-name):
* lisp/files-x.el (modify-file-local-variable):
* lisp/files.el (locate-user-emacs-file, find-alternate-file)
(set-auto-mode, hack-one-local-variable--obsolete)
(dir-locals-set-directory-class, write-file, basic-save-buffer)
(delete-directory, copy-directory, recover-session)
(recover-session-finish, insert-directory)
(file-modes-char-to-who, file-modes-symbolic-to-number)
(move-file-to-trash):
* lisp/filesets.el (filesets-add-buffer, filesets-remove-buffer):
* lisp/find-cmd.el (find-generic, find-to-string):
* lisp/finder.el (finder-commentary):
* lisp/font-lock.el (font-lock-fontify-buffer):
* lisp/format.el (format-write-file, format-find-file)
(format-insert-file):
* lisp/frame.el (get-device-terminal, select-frame-by-name):
* lisp/fringe.el (fringe--check-style):
* lisp/gnus/nnmairix.el (nnmairix-widget-create-query):
* lisp/help-fns.el (help-fns--key-bindings)
(help-fns--compiler-macro, help-fns--parent-mode)
(help-fns--obsolete, help-fns--interactive-only)
(describe-function-1, describe-variable):
* lisp/help.el (describe-mode)
(describe-minor-mode-from-indicator):
* lisp/image.el (image-type):
* lisp/international/ccl.el (ccl-dump):
* lisp/international/fontset.el (x-must-resolve-font-name):
* lisp/international/mule-cmds.el (prefer-coding-system)
(select-safe-coding-system-interactively)
(select-safe-coding-system, activate-input-method)
(toggle-input-method, describe-current-input-method)
(describe-language-environment):
* lisp/international/mule-conf.el (code-offset):
* lisp/international/mule-diag.el (describe-character-set)
(list-input-methods-1):
* lisp/mail/feedmail.el (feedmail-run-the-queue):
* lisp/mouse.el (minor-mode-menu-from-indicator):
* lisp/mpc.el (mpc-playlist-rename):
* lisp/msb.el (msb--choose-menu):
* lisp/net/ange-ftp.el (ange-ftp-shell-command):
* lisp/net/imap.el (imap-interactive-login):
* lisp/net/mairix.el (mairix-widget-create-query):
* lisp/net/newst-backend.el (newsticker--sentinel-work):
* lisp/net/newst-treeview.el (newsticker--treeview-load):
* lisp/net/rlogin.el (rlogin):
* lisp/obsolete/iswitchb.el (iswitchb-possible-new-buffer):
* lisp/obsolete/otodo-mode.el (todo-more-important-p):
* lisp/obsolete/pgg-gpg.el (pgg-gpg-process-region):
* lisp/obsolete/pgg-pgp.el (pgg-pgp-process-region):
* lisp/obsolete/pgg-pgp5.el (pgg-pgp5-process-region):
* lisp/org/ob-core.el (org-babel-goto-named-src-block)
(org-babel-goto-named-result):
* lisp/org/ob-fortran.el (org-babel-fortran-ensure-main-wrap):
* lisp/org/ob-ref.el (org-babel-ref-resolve):
* lisp/org/org-agenda.el (org-agenda-prepare):
* lisp/org/org-clock.el (org-clock-notify-once-if-expired)
(org-clock-resolve):
* lisp/org/org-ctags.el (org-ctags-ask-rebuild-tags-file-then-find-tag):
* lisp/org/org-feed.el (org-feed-parse-atom-entry):
* lisp/org/org-habit.el (org-habit-parse-todo):
* lisp/org/org-mouse.el (org-mouse-popup-global-menu)
(org-mouse-context-menu):
* lisp/org/org-table.el (org-table-edit-formulas):
* lisp/org/ox.el (org-export-async-start):
* lisp/proced.el (proced-log):
* lisp/progmodes/ada-mode.el (ada-get-indent-case)
(ada-check-matching-start, ada-goto-matching-start):
* lisp/progmodes/ada-prj.el (ada-prj-display-page):
* lisp/progmodes/ada-xref.el (ada-find-executable):
* lisp/progmodes/ebrowse.el (ebrowse-tags-apropos):
* lisp/progmodes/etags.el (etags-tags-apropos-additional):
* lisp/progmodes/flymake.el (flymake-parse-err-lines)
(flymake-start-syntax-check-process):
* lisp/progmodes/python.el (python-shell-get-process-or-error)
(python-define-auxiliary-skeleton):
* lisp/progmodes/sql.el (sql-comint):
* lisp/progmodes/verilog-mode.el (verilog-load-file-at-point):
* lisp/progmodes/vhdl-mode.el (vhdl-widget-directory-validate):
* lisp/recentf.el (recentf-open-files):
* lisp/replace.el (query-replace-read-from)
(occur-after-change-function, occur-1):
* lisp/scroll-bar.el (scroll-bar-columns):
* lisp/server.el (server-get-auth-key):
* lisp/simple.el (execute-extended-command)
(undo-outer-limit-truncate, list-processes--refresh)
(compose-mail, set-variable, choose-completion-string)
(define-alternatives):
* lisp/startup.el (site-run-file, tty-handle-args, command-line)
(command-line-1):
* lisp/subr.el (noreturn, define-error, add-to-list)
(read-char-choice, version-to-list):
* lisp/term/common-win.el (x-handle-xrm-switch)
(x-handle-name-switch, x-handle-args):
* lisp/term/x-win.el (x-handle-parent-id, x-handle-smid):
* lisp/textmodes/reftex-ref.el (reftex-label):
* lisp/textmodes/reftex-toc.el (reftex-toc-rename-label):
* lisp/textmodes/two-column.el (2C-split):
* lisp/tutorial.el (tutorial--describe-nonstandard-key)
(tutorial--find-changed-keys):
* lisp/type-break.el (type-break-noninteractive-query):
* lisp/wdired.el (wdired-do-renames, wdired-do-symlink-changes)
(wdired-do-perm-changes):
* lisp/whitespace.el (whitespace-report-region):
Prefer grave quoting in source-code strings used to generate help
and diagnostics.
* lisp/faces.el (face-documentation):
No need to convert quotes, since the result is a docstring.
* lisp/info.el (Info-virtual-index-find-node)
(Info-virtual-index, info-apropos):
Simplify by generating only curved quotes, since info files are
typically that ways nowadays anyway.
* lisp/international/mule-diag.el (list-input-methods):
Don’t assume text quoting style is curved.
* lisp/org/org-bibtex.el (org-bibtex-fields):
Revert my recent changes, going back to the old quoting style.
2015-09-07 15:41:44 +00:00
|
|
|
|
(throw 'exit (message "Can't add file-local variables"))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;; prefix is what comes before "local variables:" in its line.
|
|
|
|
|
;; suffix is what comes after "local variables:" in its line.
|
|
|
|
|
(let* ((prefix (buffer-substring (line-beginning-position)
|
|
|
|
|
(match-beginning 0)))
|
|
|
|
|
(suffix (buffer-substring (point) (line-end-position)))
|
|
|
|
|
(prefix-re (concat "^" (regexp-quote prefix)))
|
|
|
|
|
(suffix-re (concat (regexp-quote suffix) "$")))
|
|
|
|
|
|
|
|
|
|
;; Find or add missing "End:".
|
|
|
|
|
(forward-line 1)
|
|
|
|
|
(setq beg (point))
|
|
|
|
|
(save-excursion
|
|
|
|
|
(unless (let ((case-fold-search t))
|
|
|
|
|
(re-search-forward
|
|
|
|
|
(concat prefix-re "[ \t]*End:[ \t]*" suffix-re)
|
|
|
|
|
nil t))
|
|
|
|
|
(save-excursion
|
|
|
|
|
(insert (format "%sEnd:%s\n" prefix suffix))))
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(setq end (point-marker)))
|
|
|
|
|
|
|
|
|
|
;; Find and delete all existing variable/value pairs.
|
|
|
|
|
(when (member op '(add-or-replace delete))
|
|
|
|
|
(if (and (eq op 'add-or-replace) (memq variable '(mode eval)))
|
|
|
|
|
(goto-char end)
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(while (re-search-forward
|
|
|
|
|
(format "%s%S:.*%s" prefix-re variable suffix-re) end t)
|
|
|
|
|
(delete-region (match-beginning 0) (1+ (match-end 0)))
|
|
|
|
|
(setq replaced-pos (point)))))
|
|
|
|
|
|
|
|
|
|
;; Add a new variable/value pair. Add `mode' to the start, add new
|
|
|
|
|
;; variable to the end, and add a replaced variable to its last location.
|
|
|
|
|
(when (eq op 'add-or-replace)
|
|
|
|
|
(cond
|
|
|
|
|
((eq variable 'mode) (goto-char beg))
|
|
|
|
|
((null replaced-pos) (goto-char end))
|
|
|
|
|
(replaced-pos (goto-char replaced-pos)))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(insert (format "%s%S: %S%s\n" prefix variable value suffix))))
|
|
|
|
|
|
|
|
|
|
(when interactive
|
|
|
|
|
(modify-file-local-variable-message variable value op)))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(defun add-file-local-variable (variable value &optional interactive)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
"Add file-local VARIABLE with its VALUE to the Local Variables list.
|
|
|
|
|
|
|
|
|
|
This command deletes all existing settings of VARIABLE (except `mode'
|
|
|
|
|
and `eval') and adds a new file-local VARIABLE with VALUE to the
|
|
|
|
|
Local Variables list.
|
|
|
|
|
|
|
|
|
|
If there is no Local Variables list in the current file buffer
|
|
|
|
|
then this function adds the first line containing the string
|
|
|
|
|
`Local Variables:' and the last line containing the string `End:'."
|
|
|
|
|
(interactive
|
|
|
|
|
(let ((variable (read-file-local-variable "Add file-local variable")))
|
2015-06-10 20:38:18 +00:00
|
|
|
|
;; Error before reading value.
|
|
|
|
|
(if (equal variable 'lexical-binding)
|
|
|
|
|
(user-error "The `%s' variable must be set at the start of the file"
|
|
|
|
|
variable))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(list variable (read-file-local-variable-value variable) t)))
|
2015-06-10 20:38:18 +00:00
|
|
|
|
(if (equal variable 'lexical-binding)
|
|
|
|
|
(user-error "The `%s' variable must be set at the start of the file"
|
|
|
|
|
variable))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(modify-file-local-variable variable value 'add-or-replace interactive))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(defun delete-file-local-variable (variable &optional interactive)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
"Delete all settings of file-local VARIABLE from the Local Variables list."
|
|
|
|
|
(interactive
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(list (read-file-local-variable "Delete file-local variable") t))
|
|
|
|
|
(modify-file-local-variable variable nil 'delete interactive))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(defun modify-file-local-variable-prop-line (variable value op &optional interactive)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
"Modify file-local VARIABLE in the -*- line depending on operation OP.
|
|
|
|
|
|
|
|
|
|
If OP is `add-or-replace' then delete all existing settings of
|
|
|
|
|
VARIABLE (except `mode' and `eval') and add a new file-local VARIABLE
|
|
|
|
|
with VALUE to the -*- line.
|
|
|
|
|
|
|
|
|
|
If there is no -*- line at the beginning of the current file buffer
|
|
|
|
|
and OP is not `delete' then this function adds the -*- line.
|
|
|
|
|
|
|
|
|
|
If OP is `delete' then delete all existing settings of VARIABLE
|
|
|
|
|
from the -*- line ignoring the input argument VALUE."
|
|
|
|
|
(catch 'exit
|
|
|
|
|
(let ((beg (point)) end replaced-pos)
|
|
|
|
|
(unless enable-local-variables
|
|
|
|
|
(throw 'exit (message "File-local variables are disabled")))
|
|
|
|
|
|
|
|
|
|
;; Find the -*- line at the beginning of the current buffer.
|
|
|
|
|
(widen)
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(setq end (set-auto-mode-1))
|
|
|
|
|
|
|
|
|
|
(if end
|
|
|
|
|
(setq beg (point-marker) end (copy-marker end))
|
|
|
|
|
|
|
|
|
|
;; Add the -*- line if not found.
|
|
|
|
|
;; Don't add the -*- line for the deletion operation.
|
|
|
|
|
(when (eq op 'delete)
|
|
|
|
|
(throw 'exit (progn (goto-char beg)
|
|
|
|
|
(message "The -*- line not found"))))
|
|
|
|
|
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
|
2013-06-15 22:44:38 +00:00
|
|
|
|
;; Skip interpreter magic line "#!" or XML declaration.
|
|
|
|
|
(when (or (looking-at file-auto-mode-skip)
|
|
|
|
|
(looking-at "<\\?xml[^>\n]*>$"))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(forward-line 1))
|
|
|
|
|
|
|
|
|
|
(let ((comment-style 'plain)
|
2013-06-15 22:44:38 +00:00
|
|
|
|
(comment-start (or comment-start ";;; "))
|
|
|
|
|
(line-beg (line-beginning-position))
|
|
|
|
|
(ce nil))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(comment-normalize-vars)
|
2013-06-15 22:44:38 +00:00
|
|
|
|
;; If the first line contains a comment.
|
|
|
|
|
(if (save-excursion
|
|
|
|
|
(and (looking-at comment-start-skip)
|
|
|
|
|
(goto-char (match-end 0))
|
|
|
|
|
(re-search-forward comment-end-skip)
|
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
|
;; Still on the same line?
|
|
|
|
|
(equal line-beg (line-beginning-position))
|
|
|
|
|
(setq ce (point))))
|
|
|
|
|
;; Add local variables to the end of the existing comment.
|
|
|
|
|
(progn
|
|
|
|
|
(goto-char ce)
|
|
|
|
|
(insert " -*-")
|
|
|
|
|
(setq beg (point-marker))
|
|
|
|
|
(setq end (point-marker))
|
|
|
|
|
(insert "-*-"))
|
|
|
|
|
;; Otherwise, add a new comment before the first line.
|
|
|
|
|
(comment-region
|
|
|
|
|
(prog1 (point)
|
|
|
|
|
(insert "-*-")
|
|
|
|
|
(setq beg (point-marker))
|
|
|
|
|
(setq end (point-marker))
|
|
|
|
|
(insert "-*-\n"))
|
|
|
|
|
(point)))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
(cond
|
|
|
|
|
((looking-at "[ \t]*\\([^ \t\n\r:;]+\\)\\([ \t]*-\\*-\\)")
|
|
|
|
|
;; Simple form: "-*- MODENAME -*-".
|
|
|
|
|
(if (eq variable 'mode)
|
|
|
|
|
;; Replace or delete MODENAME
|
|
|
|
|
(progn
|
|
|
|
|
(when (member op '(add-or-replace delete))
|
|
|
|
|
(delete-region (match-beginning 1) (match-end 1)))
|
|
|
|
|
(when (eq op 'add-or-replace)
|
|
|
|
|
(goto-char (match-beginning 1))
|
|
|
|
|
(insert (format "%S" value))))
|
|
|
|
|
;; Else, turn `MODENAME' into `mode:MODENAME'
|
|
|
|
|
;; and add `VARIABLE: VALUE;'
|
|
|
|
|
(goto-char (match-beginning 2))
|
|
|
|
|
(insert (format "; %S: %S; " variable value))
|
|
|
|
|
(goto-char (match-beginning 1))
|
|
|
|
|
(insert " mode: ")))
|
|
|
|
|
|
|
|
|
|
(t
|
|
|
|
|
;; Hairy form: '-*-' [ <variable> ':' <value> ';' ]* '-*-'
|
|
|
|
|
;; Find and delete all existing variable/value pairs.
|
|
|
|
|
(when (member op '(add-or-replace delete))
|
|
|
|
|
(if (and (eq op 'add-or-replace) (memq variable '(mode eval)))
|
|
|
|
|
(goto-char end)
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(while (< (point) end)
|
|
|
|
|
(or (looking-at "[ \t]*\\([^ \t\n:]+\\)[ \t]*:[ \t]*")
|
|
|
|
|
(throw 'exit (message "Malformed -*- line")))
|
|
|
|
|
(goto-char (match-end 0))
|
2011-04-19 13:44:55 +00:00
|
|
|
|
(let ((key (intern (match-string 1))))
|
|
|
|
|
(save-restriction
|
|
|
|
|
(narrow-to-region (point) end)
|
|
|
|
|
(let ((read-circle nil))
|
|
|
|
|
(read (current-buffer))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(skip-chars-forward " \t;")
|
|
|
|
|
(when (eq key variable)
|
|
|
|
|
(delete-region (match-beginning 0) (point))
|
|
|
|
|
(setq replaced-pos (point)))))))
|
|
|
|
|
;; Add a new variable/value pair. Add `mode' to the start, add new
|
|
|
|
|
;; variable to the end, and add a replaced variable to its last location.
|
|
|
|
|
(when (eq op 'add-or-replace)
|
|
|
|
|
(cond
|
|
|
|
|
((eq variable 'mode) (goto-char beg))
|
|
|
|
|
((null replaced-pos) (goto-char end))
|
|
|
|
|
(replaced-pos (goto-char replaced-pos)))
|
2018-08-14 08:44:18 +00:00
|
|
|
|
(if (and (save-excursion
|
|
|
|
|
(skip-chars-backward " \t")
|
|
|
|
|
(not (eq (char-before) ?\;)))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(not (equal (point) (marker-position beg)))
|
|
|
|
|
;; When existing `-*- -*-' is empty, beg > end.
|
|
|
|
|
(not (> (marker-position beg) (marker-position end))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(insert ";"))
|
|
|
|
|
(unless (eq (char-before) ?\s) (insert " "))
|
|
|
|
|
(insert (format "%S: %S;" variable value))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(unless (eq (char-after) ?\s) (insert " ")))))
|
|
|
|
|
|
|
|
|
|
(when interactive
|
|
|
|
|
(modify-file-local-variable-message variable value op)))))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(defun add-file-local-variable-prop-line (variable value &optional interactive)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
"Add file-local VARIABLE with its VALUE to the -*- line.
|
|
|
|
|
|
|
|
|
|
This command deletes all existing settings of VARIABLE (except `mode'
|
|
|
|
|
and `eval') and adds a new file-local VARIABLE with VALUE to
|
|
|
|
|
the -*- line.
|
|
|
|
|
|
|
|
|
|
If there is no -*- line at the beginning of the current file buffer
|
|
|
|
|
then this function adds it."
|
|
|
|
|
(interactive
|
|
|
|
|
(let ((variable (read-file-local-variable "Add -*- file-local variable")))
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(list variable (read-file-local-variable-value variable) t)))
|
|
|
|
|
(modify-file-local-variable-prop-line variable value 'add-or-replace interactive))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(defun delete-file-local-variable-prop-line (variable &optional interactive)
|
2009-08-12 20:29:30 +00:00
|
|
|
|
"Delete all settings of file-local VARIABLE from the -*- line."
|
|
|
|
|
(interactive
|
2013-06-18 20:38:43 +00:00
|
|
|
|
(list (read-file-local-variable "Delete -*- file-local variable") t))
|
|
|
|
|
(modify-file-local-variable-prop-line variable nil 'delete interactive))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
2011-04-19 13:44:55 +00:00
|
|
|
|
(defvar auto-insert) ; from autoinsert.el
|
|
|
|
|
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(defun modify-dir-local-variable (mode variable value op)
|
|
|
|
|
"Modify directory-local VARIABLE in .dir-locals.el depending on operation OP.
|
|
|
|
|
|
|
|
|
|
If OP is `add-or-replace' then delete all existing settings of
|
|
|
|
|
VARIABLE (except `mode' and `eval') and add a new directory-local VARIABLE
|
|
|
|
|
with VALUE to the MODE alist where MODE can be a mode name symbol or
|
|
|
|
|
a subdirectory name.
|
|
|
|
|
|
|
|
|
|
If .dir-locals.el was not found and OP is not `delete' then create
|
|
|
|
|
this file in the current directory.
|
|
|
|
|
|
|
|
|
|
If OP is `delete' then delete all existing settings of VARIABLE
|
2009-10-04 01:44:39 +00:00
|
|
|
|
from the MODE alist ignoring the input argument VALUE."
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(catch 'exit
|
|
|
|
|
(unless enable-local-variables
|
|
|
|
|
(throw 'exit (message "Directory-local variables are disabled")))
|
2016-01-25 16:56:08 +00:00
|
|
|
|
(let* ((dir-or-cache (and (buffer-file-name)
|
|
|
|
|
(not (file-remote-p (buffer-file-name)))
|
|
|
|
|
(dir-locals-find-file (buffer-file-name))))
|
|
|
|
|
(variables-file
|
2015-11-07 13:54:56 +00:00
|
|
|
|
;; If there are several .dir-locals, the user probably
|
|
|
|
|
;; wants to edit the last one (the highest priority).
|
2016-01-25 16:56:08 +00:00
|
|
|
|
(cond ((stringp dir-or-cache)
|
|
|
|
|
(car (last (dir-locals--all-files dir-or-cache))))
|
|
|
|
|
((consp dir-or-cache) ; result from cache
|
|
|
|
|
;; If cache element has an mtime, assume it came
|
|
|
|
|
;; from a file. Otherwise, assume it was set
|
|
|
|
|
;; directly.
|
|
|
|
|
(if (nth 2 dir-or-cache)
|
|
|
|
|
(car (last (dir-locals--all-files (car dir-or-cache))))
|
|
|
|
|
(cadr dir-or-cache)))
|
2016-01-16 08:50:46 +00:00
|
|
|
|
;; Try to make a proper file-name.
|
2016-01-25 16:56:08 +00:00
|
|
|
|
(t (expand-file-name dir-locals-file))))
|
|
|
|
|
variables)
|
2011-02-24 08:45:25 +00:00
|
|
|
|
;; I can't be bothered to handle this case right now.
|
|
|
|
|
;; Dir locals were set directly from a class. You need to
|
|
|
|
|
;; directly modify the class in dir-locals-class-alist.
|
|
|
|
|
(and variables-file (not (stringp variables-file))
|
|
|
|
|
(throw 'exit (message "Directory locals were not set from a file")))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
;; Don't create ".dir-locals.el" for the deletion operation.
|
2011-02-24 08:45:25 +00:00
|
|
|
|
(and (eq op 'delete)
|
|
|
|
|
(or (not variables-file)
|
|
|
|
|
(not (file-exists-p variables-file)))
|
|
|
|
|
(throw 'exit (message "No .dir-locals.el file was found")))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(let ((auto-insert nil))
|
|
|
|
|
(find-file variables-file))
|
|
|
|
|
(widen)
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
|
|
|
|
|
;; Read alist of directory-local variables.
|
|
|
|
|
(ignore-errors
|
|
|
|
|
(delete-region
|
|
|
|
|
(prog1 (point)
|
|
|
|
|
(setq variables (let ((read-circle nil))
|
|
|
|
|
(read (current-buffer)))))
|
|
|
|
|
(point)))
|
|
|
|
|
|
|
|
|
|
;; Add or replace variable in alist of directory-local variables.
|
|
|
|
|
(let ((mode-assoc (assoc mode variables)))
|
|
|
|
|
(if mode-assoc
|
|
|
|
|
(setq variables
|
|
|
|
|
(cons (cons mode
|
|
|
|
|
(if (eq op 'delete)
|
|
|
|
|
(assq-delete-all variable (cdr mode-assoc))
|
|
|
|
|
(cons
|
|
|
|
|
(cons variable value)
|
|
|
|
|
(if (memq variable '(mode eval))
|
|
|
|
|
(cdr mode-assoc)
|
|
|
|
|
(assq-delete-all variable (cdr mode-assoc))))))
|
2018-11-07 22:27:58 +00:00
|
|
|
|
(assoc-delete-all mode variables)))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(setq variables
|
|
|
|
|
(cons `(,mode . ((,variable . ,value)))
|
|
|
|
|
variables))))
|
|
|
|
|
|
2019-08-18 22:49:24 +00:00
|
|
|
|
;; Invalidate cache (may be needed if this .dir-locals.el file
|
|
|
|
|
;; will be written with the same timestamp as is already present
|
|
|
|
|
;; in the cache, see bug#13860).
|
|
|
|
|
(setq dir-locals-directory-cache
|
|
|
|
|
(assoc-delete-all (file-name-directory variables-file)
|
|
|
|
|
dir-locals-directory-cache))
|
|
|
|
|
|
2009-08-12 20:29:30 +00:00
|
|
|
|
;; Insert modified alist of directory-local variables.
|
|
|
|
|
(insert ";;; Directory Local Variables\n")
|
2013-06-25 20:23:10 +00:00
|
|
|
|
(insert ";;; For more information see (info \"(emacs) Directory Variables\")\n\n")
|
2018-09-25 19:40:23 +00:00
|
|
|
|
(princ (dir-locals-to-string
|
2018-09-24 20:52:57 +00:00
|
|
|
|
(sort variables
|
|
|
|
|
(lambda (a b)
|
|
|
|
|
(cond
|
|
|
|
|
((null (car a)) t)
|
|
|
|
|
((null (car b)) nil)
|
|
|
|
|
((and (symbolp (car a)) (stringp (car b))) t)
|
|
|
|
|
((and (symbolp (car b)) (stringp (car a))) nil)
|
|
|
|
|
(t (string< (car a) (car b)))))))
|
|
|
|
|
(current-buffer))
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(indent-sexp))))
|
|
|
|
|
|
2018-09-25 19:40:23 +00:00
|
|
|
|
(defun dir-locals-to-string (variables)
|
2018-09-24 20:52:57 +00:00
|
|
|
|
"Output alists of VARIABLES to string in dotted pair notation syntax."
|
|
|
|
|
(format "(%s)" (mapconcat
|
2018-09-25 19:40:23 +00:00
|
|
|
|
(lambda (mode-variables)
|
2018-09-24 20:52:57 +00:00
|
|
|
|
(format "(%S . %s)"
|
2018-09-25 19:40:23 +00:00
|
|
|
|
(car mode-variables)
|
2018-09-24 20:52:57 +00:00
|
|
|
|
(format "(%s)" (mapconcat
|
|
|
|
|
(lambda (variable-value)
|
2018-11-07 22:27:58 +00:00
|
|
|
|
(format "(%S . %s)"
|
2018-09-24 20:52:57 +00:00
|
|
|
|
(car variable-value)
|
2018-11-07 22:27:58 +00:00
|
|
|
|
(string-trim-right
|
|
|
|
|
(pp-to-string
|
|
|
|
|
(cdr variable-value)))))
|
2018-09-25 19:40:23 +00:00
|
|
|
|
(cdr mode-variables) "\n"))))
|
2018-09-24 20:52:57 +00:00
|
|
|
|
variables "\n")))
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun add-dir-local-variable (mode variable value)
|
|
|
|
|
"Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el."
|
|
|
|
|
(interactive
|
|
|
|
|
(let (variable)
|
|
|
|
|
(list
|
|
|
|
|
(read-file-local-variable-mode)
|
|
|
|
|
(setq variable (read-file-local-variable "Add directory-local variable"))
|
|
|
|
|
(read-file-local-variable-value variable))))
|
|
|
|
|
(modify-dir-local-variable mode variable value 'add-or-replace))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun delete-dir-local-variable (mode variable)
|
|
|
|
|
"Delete all MODE settings of file-local VARIABLE from .dir-locals.el."
|
|
|
|
|
(interactive
|
|
|
|
|
(list
|
|
|
|
|
(read-file-local-variable-mode)
|
|
|
|
|
(read-file-local-variable "Delete directory-local variable")))
|
|
|
|
|
(modify-dir-local-variable mode variable nil 'delete))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun copy-file-locals-to-dir-locals ()
|
|
|
|
|
"Copy file-local variables to .dir-locals.el."
|
|
|
|
|
(interactive)
|
|
|
|
|
(dolist (elt file-local-variables-alist)
|
|
|
|
|
(unless (assq (car elt) dir-local-variables-alist)
|
|
|
|
|
(add-dir-local-variable major-mode (car elt) (cdr elt)))))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun copy-dir-locals-to-file-locals ()
|
|
|
|
|
"Copy directory-local variables to the Local Variables list."
|
|
|
|
|
(interactive)
|
|
|
|
|
(dolist (elt dir-local-variables-alist)
|
|
|
|
|
(add-file-local-variable (car elt) (cdr elt))))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun copy-dir-locals-to-file-locals-prop-line ()
|
2009-10-04 01:44:39 +00:00
|
|
|
|
"Copy directory-local variables to the -*- line."
|
2009-08-12 20:29:30 +00:00
|
|
|
|
(interactive)
|
|
|
|
|
(dolist (elt dir-local-variables-alist)
|
|
|
|
|
(add-file-local-variable-prop-line (car elt) (cdr elt))))
|
|
|
|
|
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
;;; connection-local variables.
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defvar enable-connection-local-variables t
|
|
|
|
|
"Non-nil means enable use of connection-local variables.")
|
|
|
|
|
|
|
|
|
|
(defvar connection-local-variables-alist nil
|
|
|
|
|
"Alist of connection-local variable settings in the current buffer.
|
|
|
|
|
Each element in this list has the form (VAR . VALUE), where VAR
|
|
|
|
|
is a connection-local variable (a symbol) and VALUE is its value.
|
|
|
|
|
The actual value in the buffer may differ from VALUE, if it is
|
|
|
|
|
changed by the user.")
|
|
|
|
|
(make-variable-buffer-local 'connection-local-variables-alist)
|
|
|
|
|
(setq ignored-local-variables
|
|
|
|
|
(cons 'connection-local-variables-alist ignored-local-variables))
|
|
|
|
|
|
2019-03-09 15:44:24 +00:00
|
|
|
|
(defvar connection-local-profile-alist nil
|
2017-02-19 16:14:35 +00:00
|
|
|
|
"Alist mapping connection profiles to variable lists.
|
|
|
|
|
Each element in this list has the form (PROFILE VARIABLES).
|
|
|
|
|
PROFILE is the name of a connection profile (a symbol).
|
2016-11-14 12:56:58 +00:00
|
|
|
|
VARIABLES is a list that declares connection-local variables for
|
2017-02-19 16:14:35 +00:00
|
|
|
|
PROFILE. An element in VARIABLES is an alist whose elements are
|
|
|
|
|
of the form (VAR . VALUE).")
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
2019-03-09 15:44:24 +00:00
|
|
|
|
(defvar connection-local-criteria-alist nil
|
2017-02-19 16:14:35 +00:00
|
|
|
|
"Alist mapping connection criteria to connection profiles.
|
|
|
|
|
Each element in this list has the form (CRITERIA PROFILES).
|
|
|
|
|
CRITERIA is a plist identifying a connection and the application
|
|
|
|
|
using this connection. Property names might be `:application',
|
|
|
|
|
`:protocol', `:user' and `:machine'. The property value of
|
|
|
|
|
`:application' is a symbol, all other property values are
|
|
|
|
|
strings. All properties are optional; if CRITERIA is nil, it
|
|
|
|
|
always applies.
|
|
|
|
|
PROFILES is a list of connection profiles (symbols).")
|
|
|
|
|
|
2018-07-09 14:03:49 +00:00
|
|
|
|
(defsubst connection-local-normalize-criteria (criteria)
|
|
|
|
|
"Normalize plist CRITERIA according to properties.
|
|
|
|
|
Return a reordered plist."
|
|
|
|
|
(apply
|
|
|
|
|
'append
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(mapcar
|
|
|
|
|
(lambda (property)
|
2017-04-02 09:02:54 +00:00
|
|
|
|
(when (and (plist-member criteria property) (plist-get criteria property))
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(list property (plist-get criteria property))))
|
2018-07-09 14:03:49 +00:00
|
|
|
|
'(:application :protocol :user :machine))))
|
2017-02-19 16:14:35 +00:00
|
|
|
|
|
|
|
|
|
(defsubst connection-local-get-profiles (criteria)
|
|
|
|
|
"Return the connection profiles list for CRITERIA.
|
|
|
|
|
CRITERIA is a plist identifying a connection and the application
|
|
|
|
|
using this connection, see `connection-local-criteria-alist'."
|
2018-07-09 14:03:49 +00:00
|
|
|
|
(let (profiles)
|
|
|
|
|
(dolist (crit-alist connection-local-criteria-alist)
|
|
|
|
|
(let ((crit criteria)
|
|
|
|
|
(match t))
|
|
|
|
|
(while (and crit match)
|
|
|
|
|
(when (plist-member (car crit-alist) (car crit))
|
|
|
|
|
(setq match (equal (plist-get (car crit-alist) (car crit))
|
|
|
|
|
(plist-get criteria (car crit)))))
|
|
|
|
|
(setq crit (cddr crit)))
|
|
|
|
|
(when match
|
|
|
|
|
(setq profiles (append profiles (cdr crit-alist))))))
|
|
|
|
|
(delete-dups profiles)))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(defun connection-local-set-profiles (criteria &rest profiles)
|
2017-04-02 09:02:54 +00:00
|
|
|
|
"Add PROFILES for CRITERIA.
|
|
|
|
|
CRITERIA is a plist identifying a connection and the application
|
|
|
|
|
using this connection, see `connection-local-criteria-alist'.
|
|
|
|
|
PROFILES are the names of connection profiles (a symbol).
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
When a connection to a remote server is opened and CRITERIA
|
2017-02-19 16:14:35 +00:00
|
|
|
|
matches to that server, the connection-local variables from
|
|
|
|
|
PROFILES are applied to the corresponding process buffer. The
|
|
|
|
|
variables for a connection profile are defined using
|
|
|
|
|
`connection-local-set-profile-variables'."
|
|
|
|
|
(unless (listp criteria)
|
2016-11-14 12:56:58 +00:00
|
|
|
|
(error "Wrong criteria `%s'" criteria))
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(dolist (profile profiles)
|
|
|
|
|
(unless (assq profile connection-local-profile-alist)
|
|
|
|
|
(error "No such connection profile `%s'" (symbol-name profile))))
|
2018-07-09 14:03:49 +00:00
|
|
|
|
(let* ((criteria (connection-local-normalize-criteria criteria))
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(slot (assoc criteria connection-local-criteria-alist)))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
(if slot
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(setcdr slot (delete-dups (append (cdr slot) profiles)))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
(setq connection-local-criteria-alist
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(cons (cons criteria (delete-dups profiles))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
connection-local-criteria-alist)))))
|
|
|
|
|
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(defsubst connection-local-get-profile-variables (profile)
|
|
|
|
|
"Return the connection-local variable list for PROFILE."
|
|
|
|
|
(cdr (assq profile connection-local-profile-alist)))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(defun connection-local-set-profile-variables (profile variables)
|
|
|
|
|
"Map the symbol PROFILE to a list of variable settings.
|
2016-11-14 12:56:58 +00:00
|
|
|
|
VARIABLES is a list that declares connection-local variables for
|
2017-02-19 16:14:35 +00:00
|
|
|
|
the connection profile. An element in VARIABLES is an alist
|
|
|
|
|
whose elements are of the form (VAR . VALUE).
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
When a connection to a remote server is opened, the server's
|
2017-02-19 16:14:35 +00:00
|
|
|
|
connection profiles are found. A server may be assigned a
|
2017-12-10 03:52:50 +00:00
|
|
|
|
connection profile using `connection-local-set-profiles'. Then
|
2017-02-19 16:14:35 +00:00
|
|
|
|
variables are set in the server's process buffer according to the
|
|
|
|
|
VARIABLES list of the connection profile. The list is processed
|
|
|
|
|
in order."
|
|
|
|
|
(setf (alist-get profile connection-local-profile-alist) variables))
|
|
|
|
|
|
|
|
|
|
(defun hack-connection-local-variables (criteria)
|
|
|
|
|
"Read connection-local variables according to CRITERIA.
|
|
|
|
|
Store the connection-local variables in buffer local
|
|
|
|
|
variable`connection-local-variables-alist'.
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
This does nothing if `enable-connection-local-variables' is nil."
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(when enable-connection-local-variables
|
|
|
|
|
;; Filter connection profiles.
|
|
|
|
|
(dolist (profile (connection-local-get-profiles criteria))
|
|
|
|
|
;; Loop over variables.
|
|
|
|
|
(dolist (variable (connection-local-get-profile-variables profile))
|
|
|
|
|
(unless (assq (car variable) connection-local-variables-alist)
|
2019-03-09 15:44:24 +00:00
|
|
|
|
(push variable connection-local-variables-alist))))
|
2019-03-23 08:55:04 +00:00
|
|
|
|
;; Push them to `file-local-variables-alist'. Connection-local
|
|
|
|
|
;; variables do not appear from external files. So we can regard
|
|
|
|
|
;; them as safe.
|
2019-03-24 13:24:31 +00:00
|
|
|
|
(let ((enable-local-variables :all))
|
2019-03-23 08:55:04 +00:00
|
|
|
|
(hack-local-variables-filter connection-local-variables-alist nil))))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(defun hack-connection-local-variables-apply (criteria)
|
|
|
|
|
"Apply connection-local variables identified by CRITERIA.
|
2016-11-14 12:56:58 +00:00
|
|
|
|
Other local variables, like file-local and dir-local variables,
|
|
|
|
|
will not be changed."
|
2017-02-19 16:14:35 +00:00
|
|
|
|
(hack-connection-local-variables criteria)
|
2016-11-14 12:56:58 +00:00
|
|
|
|
(let ((file-local-variables-alist
|
|
|
|
|
(copy-tree connection-local-variables-alist)))
|
|
|
|
|
(hack-local-variables-apply)))
|
|
|
|
|
|
2019-03-09 15:44:24 +00:00
|
|
|
|
(defsubst connection-local-criteria-for-default-directory ()
|
|
|
|
|
"Return a connection-local criteria, which represents `default-directory'."
|
|
|
|
|
(when (file-remote-p default-directory)
|
|
|
|
|
`(:application tramp
|
|
|
|
|
:protocol ,(file-remote-p default-directory 'method)
|
|
|
|
|
:user ,(file-remote-p default-directory 'user)
|
|
|
|
|
:machine ,(file-remote-p default-directory 'host))))
|
|
|
|
|
|
2016-11-14 12:56:58 +00:00
|
|
|
|
;;;###autoload
|
2019-03-09 15:44:24 +00:00
|
|
|
|
(defmacro with-connection-local-variables (&rest body)
|
|
|
|
|
"Apply connection-local variables according to `default-directory'.
|
2017-04-02 09:02:54 +00:00
|
|
|
|
Execute BODY, and unwind connection-local variables."
|
2019-03-09 15:44:24 +00:00
|
|
|
|
(declare (debug t))
|
|
|
|
|
`(if (file-remote-p default-directory)
|
|
|
|
|
(let ((enable-connection-local-variables t)
|
|
|
|
|
(old-buffer-local-variables (buffer-local-variables))
|
|
|
|
|
connection-local-variables-alist)
|
|
|
|
|
(hack-connection-local-variables-apply
|
|
|
|
|
(connection-local-criteria-for-default-directory))
|
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn ,@body)
|
|
|
|
|
;; Cleanup.
|
|
|
|
|
(dolist (variable connection-local-variables-alist)
|
|
|
|
|
(let ((elt (assq (car variable) old-buffer-local-variables)))
|
|
|
|
|
(if elt
|
|
|
|
|
(set (make-local-variable (car elt)) (cdr elt))
|
|
|
|
|
(kill-local-variable (car variable)))))))
|
|
|
|
|
;; No connection-local variables to apply.
|
|
|
|
|
,@body))
|
2016-11-14 12:56:58 +00:00
|
|
|
|
|
2009-08-12 20:29:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(provide 'files-x)
|
2009-08-14 04:47:38 +00:00
|
|
|
|
|
2009-08-12 20:29:30 +00:00
|
|
|
|
;;; files-x.el ends here
|