diff options
| author | Michael Olson | 2008-05-19 22:36:09 +0000 |
|---|---|---|
| committer | Michael Olson | 2008-05-19 22:36:09 +0000 |
| commit | 1b21ee065d77baee6da0c46a207bfb44d7cc0a95 (patch) | |
| tree | ac173ee06682f6fe2d09403c2be5d246b9d26558 | |
| parent | ad97b375e8189e1826d562898ea78e4f3bb94bda (diff) | |
| download | emacs-1b21ee065d77baee6da0c46a207bfb44d7cc0a95.tar.gz emacs-1b21ee065d77baee6da0c46a207bfb44d7cc0a95.zip | |
Implement Project-local variables.
| -rw-r--r-- | doc/emacs/custom.texi | 60 | ||||
| -rw-r--r-- | etc/NEWS | 3 | ||||
| -rw-r--r-- | lisp/files.el | 260 |
3 files changed, 279 insertions, 44 deletions
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index e270f863253..a85925c0f05 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi | |||
| @@ -796,6 +796,7 @@ here we describe other aspects of Emacs variables. | |||
| 796 | of Emacs to run on particular occasions. | 796 | of Emacs to run on particular occasions. |
| 797 | * Locals:: Per-buffer values of variables. | 797 | * Locals:: Per-buffer values of variables. |
| 798 | * File Variables:: How files can specify variable values. | 798 | * File Variables:: How files can specify variable values. |
| 799 | * Directory Variables:: How variable values can be specified by directory. | ||
| 799 | @end menu | 800 | @end menu |
| 800 | 801 | ||
| 801 | @node Examining | 802 | @node Examining |
| @@ -1262,6 +1263,65 @@ customizable list of eval forms which are safe. Emacs does not ask | |||
| 1262 | for confirmation when it finds these forms for the @code{eval} | 1263 | for confirmation when it finds these forms for the @code{eval} |
| 1263 | variable. | 1264 | variable. |
| 1264 | 1265 | ||
| 1266 | @node Directory Variables | ||
| 1267 | @subsection Per-Directory Local Variables | ||
| 1268 | @cindex local variables in directories | ||
| 1269 | @cindex directory local variables | ||
| 1270 | |||
| 1271 | Emacs provides a way to specify local variable values per-directory. | ||
| 1272 | This can be done one of two ways. | ||
| 1273 | |||
| 1274 | The first approach is to put a special file, named | ||
| 1275 | @file{.dir-settings.el}, in a directory. When opening a file, Emacs | ||
| 1276 | searches for @file{.dir-settings.el} starting in the file's directory | ||
| 1277 | and then moving up the directory hierarchy. If | ||
| 1278 | @file{.dir-settings.el} is found, Emacs applies variable settings from | ||
| 1279 | the file to the new buffer. If the file is remote, Emacs skips this | ||
| 1280 | search, because it would be too slow. | ||
| 1281 | |||
| 1282 | The file should hold a specially-constructed list. This list maps | ||
| 1283 | Emacs mode names (symbols) to alists; each alist maps variable names | ||
| 1284 | to values. The special mode name @samp{nil} means that the alist | ||
| 1285 | should be applied to all buffers. Finally, a string key can be used | ||
| 1286 | to specify an alist which applies to a relative subdirectory in the | ||
| 1287 | project. | ||
| 1288 | |||
| 1289 | @example | ||
| 1290 | ((nil . ((indent-tabs-mode . t) | ||
| 1291 | (tab-width . 4) | ||
| 1292 | (fill-column . 80))) | ||
| 1293 | (c-mode . ((c-file-style . "BSD"))) | ||
| 1294 | (java-mode . ((c-file-style . "BSD"))) | ||
| 1295 | ("src/imported" | ||
| 1296 | . ((nil . ((change-log-default-name . "ChangeLog.local")))))) | ||
| 1297 | @end example | ||
| 1298 | |||
| 1299 | This example shows some settings for a hypothetical project. This | ||
| 1300 | sets @samp{indent-tabs-mode} to @samp{t} for any file in the source | ||
| 1301 | tree, and it sets the indentation style for any C or Java source file | ||
| 1302 | to @samp{BSD}. Finally, it specifies a different @file{ChangeLog} | ||
| 1303 | file name for any file in the project that appears beneath the | ||
| 1304 | directory @file{src/imported}. | ||
| 1305 | |||
| 1306 | The second approach to directory-local settings is to explicitly | ||
| 1307 | define a project class using @code{define-project-bindings}, and then | ||
| 1308 | to tell Emacs which directory roots correspond to that class, using | ||
| 1309 | @code{set-directory-project}. You can put calls to these functions in | ||
| 1310 | your @file{.emacs}; this can useful when you can't put | ||
| 1311 | @file{.dir-settings.el} in the directory for some reason. For | ||
| 1312 | example, you could apply settings to an unwriteable directory this | ||
| 1313 | way: | ||
| 1314 | |||
| 1315 | @example | ||
| 1316 | (define-project-bindings 'unwriteable-directory | ||
| 1317 | '((nil . ((some-useful-setting . value))))) | ||
| 1318 | |||
| 1319 | (set-directory-project "/usr/include/" 'unwriteable-directory) | ||
| 1320 | @end example | ||
| 1321 | |||
| 1322 | Unsafe directory-local variables are handled in the same way as | ||
| 1323 | unsafe file-local variables. | ||
| 1324 | |||
| 1265 | @node Key Bindings | 1325 | @node Key Bindings |
| 1266 | @section Customizing Key Bindings | 1326 | @section Customizing Key Bindings |
| 1267 | @cindex key bindings | 1327 | @cindex key bindings |
| @@ -180,6 +180,9 @@ run processes remotely. | |||
| 180 | ** The new command `display-time-world' starts an updating time display | 180 | ** The new command `display-time-world' starts an updating time display |
| 181 | using several time zones, in a buffer. | 181 | using several time zones, in a buffer. |
| 182 | 182 | ||
| 183 | ** Directory-local variables are now found in .dir-settings.el. See | ||
| 184 | also `set-directory-project' and `define-project-bindings'. | ||
| 185 | |||
| 183 | ** The new function `format-seconds' converts a number of seconds into a | 186 | ** The new function `format-seconds' converts a number of seconds into a |
| 184 | readable string of days, hours, etc. | 187 | readable string of days, hours, etc. |
| 185 | 188 | ||
diff --git a/lisp/files.el b/lisp/files.el index b2f3002d3dd..3afbb2a1d18 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -1973,6 +1973,8 @@ in that case, this function acts as if `enable-local-variables' were t." | |||
| 1973 | (let ((enable-local-variables (or (not find-file) enable-local-variables))) | 1973 | (let ((enable-local-variables (or (not find-file) enable-local-variables))) |
| 1974 | (report-errors "File mode specification error: %s" | 1974 | (report-errors "File mode specification error: %s" |
| 1975 | (set-auto-mode)) | 1975 | (set-auto-mode)) |
| 1976 | (report-errors "Project local-variables error: %s" | ||
| 1977 | (hack-project-variables)) | ||
| 1976 | (report-errors "File local-variables error: %s" | 1978 | (report-errors "File local-variables error: %s" |
| 1977 | (hack-local-variables))) | 1979 | (hack-local-variables))) |
| 1978 | ;; Turn font lock off and on, to make sure it takes account of | 1980 | ;; Turn font lock off and on, to make sure it takes account of |
| @@ -2623,11 +2625,13 @@ asking you for confirmation." | |||
| 2623 | 2625 | ||
| 2624 | (put 'c-set-style 'safe-local-eval-function t) | 2626 | (put 'c-set-style 'safe-local-eval-function t) |
| 2625 | 2627 | ||
| 2626 | (defun hack-local-variables-confirm (all-vars unsafe-vars risky-vars) | 2628 | (defun hack-local-variables-confirm (all-vars unsafe-vars risky-vars project) |
| 2627 | "Get confirmation before setting up local variable values. | 2629 | "Get confirmation before setting up local variable values. |
| 2628 | ALL-VARS is the list of all variables to be set up. | 2630 | ALL-VARS is the list of all variables to be set up. |
| 2629 | UNSAFE-VARS is the list of those that aren't marked as safe or risky. | 2631 | UNSAFE-VARS is the list of those that aren't marked as safe or risky. |
| 2630 | RISKY-VARS is the list of those that are marked as risky." | 2632 | RISKY-VARS is the list of those that are marked as risky. |
| 2633 | PROJECT is a directory name if these settings come from directory-local | ||
| 2634 | settings; nil otherwise." | ||
| 2631 | (if noninteractive | 2635 | (if noninteractive |
| 2632 | nil | 2636 | nil |
| 2633 | (let ((name (if buffer-file-name | 2637 | (let ((name (if buffer-file-name |
| @@ -2641,15 +2645,16 @@ RISKY-VARS is the list of those that are marked as risky." | |||
| 2641 | (set (make-local-variable 'cursor-type) nil) | 2645 | (set (make-local-variable 'cursor-type) nil) |
| 2642 | (erase-buffer) | 2646 | (erase-buffer) |
| 2643 | (if unsafe-vars | 2647 | (if unsafe-vars |
| 2644 | (insert "The local variables list in " name | 2648 | (insert "The local variables list in " (or project name) |
| 2645 | "\ncontains values that may not be safe (*)" | 2649 | "\ncontains values that may not be safe (*)" |
| 2646 | (if risky-vars | 2650 | (if risky-vars |
| 2647 | ", and variables that are risky (**)." | 2651 | ", and variables that are risky (**)." |
| 2648 | ".")) | 2652 | ".")) |
| 2649 | (if risky-vars | 2653 | (if risky-vars |
| 2650 | (insert "The local variables list in " name | 2654 | (insert "The local variables list in " (or project name) |
| 2651 | "\ncontains variables that are risky (**).") | 2655 | "\ncontains variables that are risky (**).") |
| 2652 | (insert "A local variables list is specified in " name "."))) | 2656 | (insert "A local variables list is specified in " |
| 2657 | (or project name) "."))) | ||
| 2653 | (insert "\n\nDo you want to apply it? You can type | 2658 | (insert "\n\nDo you want to apply it? You can type |
| 2654 | y -- to apply the local variables list. | 2659 | y -- to apply the local variables list. |
| 2655 | n -- to ignore the local variables list.") | 2660 | n -- to ignore the local variables list.") |
| @@ -2771,6 +2776,50 @@ and VAL is the specified value." | |||
| 2771 | mode-specified | 2776 | mode-specified |
| 2772 | result)))) | 2777 | result)))) |
| 2773 | 2778 | ||
| 2779 | (defun hack-local-variables-apply (result project) | ||
| 2780 | "Apply an alist of local variable settings. | ||
| 2781 | RESULT is the alist. | ||
| 2782 | Will query the user when necessary." | ||
| 2783 | (dolist (ignored ignored-local-variables) | ||
| 2784 | (setq result (assq-delete-all ignored result))) | ||
| 2785 | (if (null enable-local-eval) | ||
| 2786 | (setq result (assq-delete-all 'eval result))) | ||
| 2787 | (when result | ||
| 2788 | (setq result (nreverse result)) | ||
| 2789 | ;; Find those variables that we may want to save to | ||
| 2790 | ;; `safe-local-variable-values'. | ||
| 2791 | (let (risky-vars unsafe-vars) | ||
| 2792 | (dolist (elt result) | ||
| 2793 | (let ((var (car elt)) | ||
| 2794 | (val (cdr elt))) | ||
| 2795 | ;; Don't query about the fake variables. | ||
| 2796 | (or (memq var '(mode unibyte coding)) | ||
| 2797 | (and (eq var 'eval) | ||
| 2798 | (or (eq enable-local-eval t) | ||
| 2799 | (hack-one-local-variable-eval-safep | ||
| 2800 | (eval (quote val))))) | ||
| 2801 | (safe-local-variable-p var val) | ||
| 2802 | (and (risky-local-variable-p var val) | ||
| 2803 | (push elt risky-vars)) | ||
| 2804 | (push elt unsafe-vars)))) | ||
| 2805 | (if (eq enable-local-variables :safe) | ||
| 2806 | ;; If caller wants only the safe variables, | ||
| 2807 | ;; install only them. | ||
| 2808 | (dolist (elt result) | ||
| 2809 | (unless (or (member elt unsafe-vars) | ||
| 2810 | (member elt risky-vars)) | ||
| 2811 | (hack-one-local-variable (car elt) (cdr elt)))) | ||
| 2812 | ;; Query, except in the case where all are known safe | ||
| 2813 | ;; if the user wants no query in that case. | ||
| 2814 | (if (or (and (eq enable-local-variables t) | ||
| 2815 | (null unsafe-vars) | ||
| 2816 | (null risky-vars)) | ||
| 2817 | (eq enable-local-variables :all) | ||
| 2818 | (hack-local-variables-confirm | ||
| 2819 | result unsafe-vars risky-vars project)) | ||
| 2820 | (dolist (elt result) | ||
| 2821 | (hack-one-local-variable (car elt) (cdr elt)))))))) | ||
| 2822 | |||
| 2774 | (defun hack-local-variables (&optional mode-only) | 2823 | (defun hack-local-variables (&optional mode-only) |
| 2775 | "Parse and put into effect this buffer's local variables spec. | 2824 | "Parse and put into effect this buffer's local variables spec. |
| 2776 | If MODE-ONLY is non-nil, all we do is check whether the major mode | 2825 | If MODE-ONLY is non-nil, all we do is check whether the major mode |
| @@ -2862,45 +2911,7 @@ is specified, returning t if it is specified." | |||
| 2862 | ;; variables (if MODE-ONLY is nil.) | 2911 | ;; variables (if MODE-ONLY is nil.) |
| 2863 | (if mode-only | 2912 | (if mode-only |
| 2864 | result | 2913 | result |
| 2865 | (dolist (ignored ignored-local-variables) | 2914 | (hack-local-variables-apply result nil) |
| 2866 | (setq result (assq-delete-all ignored result))) | ||
| 2867 | (if (null enable-local-eval) | ||
| 2868 | (setq result (assq-delete-all 'eval result))) | ||
| 2869 | (when result | ||
| 2870 | (setq result (nreverse result)) | ||
| 2871 | ;; Find those variables that we may want to save to | ||
| 2872 | ;; `safe-local-variable-values'. | ||
| 2873 | (let (risky-vars unsafe-vars) | ||
| 2874 | (dolist (elt result) | ||
| 2875 | (let ((var (car elt)) | ||
| 2876 | (val (cdr elt))) | ||
| 2877 | ;; Don't query about the fake variables. | ||
| 2878 | (or (memq var '(mode unibyte coding)) | ||
| 2879 | (and (eq var 'eval) | ||
| 2880 | (or (eq enable-local-eval t) | ||
| 2881 | (hack-one-local-variable-eval-safep | ||
| 2882 | (eval (quote val))))) | ||
| 2883 | (safe-local-variable-p var val) | ||
| 2884 | (and (risky-local-variable-p var val) | ||
| 2885 | (push elt risky-vars)) | ||
| 2886 | (push elt unsafe-vars)))) | ||
| 2887 | (if (eq enable-local-variables :safe) | ||
| 2888 | ;; If caller wants only the safe variables, | ||
| 2889 | ;; install only them. | ||
| 2890 | (dolist (elt result) | ||
| 2891 | (unless (or (member elt unsafe-vars) | ||
| 2892 | (member elt risky-vars)) | ||
| 2893 | (hack-one-local-variable (car elt) (cdr elt)))) | ||
| 2894 | ;; Query, except in the case where all are known safe | ||
| 2895 | ;; if the user wants no quuery in that case. | ||
| 2896 | (if (or (and (eq enable-local-variables t) | ||
| 2897 | (null unsafe-vars) | ||
| 2898 | (null risky-vars)) | ||
| 2899 | (eq enable-local-variables :all) | ||
| 2900 | (hack-local-variables-confirm | ||
| 2901 | result unsafe-vars risky-vars)) | ||
| 2902 | (dolist (elt result) | ||
| 2903 | (hack-one-local-variable (car elt) (cdr elt))))))) | ||
| 2904 | (run-hooks 'hack-local-variables-hook))))) | 2915 | (run-hooks 'hack-local-variables-hook))))) |
| 2905 | 2916 | ||
| 2906 | (defun safe-local-variable-p (sym val) | 2917 | (defun safe-local-variable-p (sym val) |
| @@ -3004,6 +3015,167 @@ already the major mode." | |||
| 3004 | (if (stringp val) | 3015 | (if (stringp val) |
| 3005 | (set-text-properties 0 (length val) nil val)) | 3016 | (set-text-properties 0 (length val) nil val)) |
| 3006 | (set (make-local-variable var) val)))) | 3017 | (set (make-local-variable var) val)))) |
| 3018 | |||
| 3019 | ;;; Handling directory local variables, aka project settings. | ||
| 3020 | |||
| 3021 | (defvar project-class-alist '() | ||
| 3022 | "Alist mapping project class names (symbols) to project variable lists.") | ||
| 3023 | |||
| 3024 | (defvar project-directory-alist '() | ||
| 3025 | "Alist mapping project directory roots to project classes.") | ||
| 3026 | |||
| 3027 | (defsubst project-get-alist (class) | ||
| 3028 | "Return the project variable list for project CLASS." | ||
| 3029 | (cdr (assq class project-class-alist))) | ||
| 3030 | |||
| 3031 | (defun project-collect-bindings-from-alist (mode-alist settings) | ||
| 3032 | "Collect local variable settings from MODE-ALIST. | ||
| 3033 | SETTINGS is the initial list of bindings. | ||
| 3034 | Returns the new list." | ||
| 3035 | (dolist (pair mode-alist settings) | ||
| 3036 | (let* ((variable (car pair)) | ||
| 3037 | (value (cdr pair)) | ||
| 3038 | (slot (assq variable settings))) | ||
| 3039 | (if slot | ||
| 3040 | (setcdr slot value) | ||
| 3041 | ;; Need a new cons in case we setcdr later. | ||
| 3042 | (push (cons variable value) settings))))) | ||
| 3043 | |||
| 3044 | (defun project-collect-binding-list (binding-list root settings) | ||
| 3045 | "Collect entries from BINDING-LIST into SETTINGS. | ||
| 3046 | ROOT is the root directory of the project. | ||
| 3047 | Return the new settings list." | ||
| 3048 | (let* ((file-name (buffer-file-name)) | ||
| 3049 | (sub-file-name (if file-name | ||
| 3050 | (substring file-name (length root))))) | ||
| 3051 | (dolist (entry binding-list settings) | ||
| 3052 | (let ((key (car entry))) | ||
| 3053 | (cond | ||
| 3054 | ((stringp key) | ||
| 3055 | ;; Don't include this in the previous condition, because we | ||
| 3056 | ;; want to filter all strings before the next condition. | ||
| 3057 | (when (and sub-file-name | ||
| 3058 | (>= (length sub-file-name) (length key)) | ||
| 3059 | (string= key (substring sub-file-name 0 (length key)))) | ||
| 3060 | (setq settings (project-collect-binding-list (cdr entry) | ||
| 3061 | root settings)))) | ||
| 3062 | ((or (not key) | ||
| 3063 | (derived-mode-p key)) | ||
| 3064 | (setq settings (project-collect-bindings-from-alist (cdr entry) | ||
| 3065 | settings)))))))) | ||
| 3066 | |||
| 3067 | (defun set-directory-project (directory class) | ||
| 3068 | "Declare that the project rooted at DIRECTORY is an instance of CLASS. | ||
| 3069 | DIRECTORY is the name of a directory, a string. | ||
| 3070 | CLASS is the name of a project class, a symbol. | ||
| 3071 | |||
| 3072 | When a file beneath DIRECTORY is visited, the mode-specific | ||
| 3073 | settings from CLASS will be applied to the buffer. The settings | ||
| 3074 | for a class are defined using `define-project-bindings'." | ||
| 3075 | (setq directory (file-name-as-directory (expand-file-name directory))) | ||
| 3076 | (unless (assq class project-class-alist) | ||
| 3077 | (error "No such project class `%s'" (symbol-name class))) | ||
| 3078 | (push (cons directory class) project-directory-alist)) | ||
| 3079 | |||
| 3080 | (defun define-project-bindings (class list) | ||
| 3081 | "Map the project type CLASS to a list of variable settings. | ||
| 3082 | CLASS is the project class, a symbol. | ||
| 3083 | LIST is a list that declares variable settings for the class. | ||
| 3084 | An element in LIST is either of the form: | ||
| 3085 | (MAJOR-MODE . ALIST) | ||
| 3086 | or | ||
| 3087 | (DIRECTORY . LIST) | ||
| 3088 | |||
| 3089 | In the first form, MAJOR-MODE is a symbol, and ALIST is an alist | ||
| 3090 | whose elements are of the form (VARIABLE . VALUE). | ||
| 3091 | |||
| 3092 | In the second form, DIRECTORY is a directory name (a string), and | ||
| 3093 | LIST is a list of the form accepted by the function. | ||
| 3094 | |||
| 3095 | When a file is visited, the file's class is found. A directory | ||
| 3096 | may be assigned a class using `set-directory-project'. Then | ||
| 3097 | variables are set in the file's buffer according to the class' | ||
| 3098 | LIST. The list is processed in order. | ||
| 3099 | |||
| 3100 | * If the element is of the form (MAJOR-MODE . ALIST), and the | ||
| 3101 | buffer's major mode is derived from MAJOR-MODE (as determined | ||
| 3102 | by `derived-mode-p'), then all the settings in ALIST are | ||
| 3103 | applied. A MAJOR-MODE of nil may be used to match any buffer. | ||
| 3104 | `make-local-variable' is called for each variable before it is | ||
| 3105 | set. | ||
| 3106 | |||
| 3107 | * If the element is of the form (DIRECTORY . LIST), and DIRECTORY | ||
| 3108 | is an initial substring of the file's directory, then LIST is | ||
| 3109 | applied by recursively following these rules." | ||
| 3110 | (let ((elt (assq class project-class-alist))) | ||
| 3111 | (if elt | ||
| 3112 | (setcdr elt list) | ||
| 3113 | (push (cons class list) project-class-alist)))) | ||
| 3114 | |||
| 3115 | (defun project-find-settings-file (file) | ||
| 3116 | "Find the settings file for FILE. | ||
| 3117 | This searches upward in the directory tree. | ||
| 3118 | If a settings file is found, the file name is returned. | ||
| 3119 | If the file is in a registered project, a cons from | ||
| 3120 | `project-directory-alist' is returned. | ||
| 3121 | Otherwise this returns nil." | ||
| 3122 | (let ((dir (file-name-directory file)) | ||
| 3123 | (result nil)) | ||
| 3124 | (while (and (not (string= dir "/")) | ||
| 3125 | (not result)) | ||
| 3126 | (cond | ||
| 3127 | ((setq result (assoc dir project-directory-alist)) | ||
| 3128 | ;; Nothing else. | ||
| 3129 | nil) | ||
| 3130 | ((file-exists-p (concat dir ".dir-settings.el")) | ||
| 3131 | (setq result (concat dir ".dir-settings.el"))) | ||
| 3132 | (t | ||
| 3133 | (setq dir (file-name-directory (directory-file-name dir)))))) | ||
| 3134 | result)) | ||
| 3135 | |||
| 3136 | (defun project-define-from-project-file (settings-file) | ||
| 3137 | "Load a settings file and register a new project class and instance. | ||
| 3138 | SETTINGS-FILE is the name of the file holding the settings to apply. | ||
| 3139 | The new class name is the same as the directory in which SETTINGS-FILE | ||
| 3140 | is found. Returns the new class name." | ||
| 3141 | (with-temp-buffer | ||
| 3142 | ;; We should probably store the modtime of SETTINGS-FILE and then | ||
| 3143 | ;; reload it whenever it changes. | ||
| 3144 | (insert-file-contents settings-file) | ||
| 3145 | (let* ((dir-name (file-name-directory settings-file)) | ||
| 3146 | (class-name (intern dir-name)) | ||
| 3147 | (list (read (current-buffer)))) | ||
| 3148 | (define-project-bindings class-name list) | ||
| 3149 | (set-directory-project dir-name class-name) | ||
| 3150 | class-name))) | ||
| 3151 | |||
| 3152 | (defun hack-project-variables () | ||
| 3153 | "Set local variables in a buffer based on project settings." | ||
| 3154 | (when (and (buffer-file-name) (not (file-remote-p (buffer-file-name)))) | ||
| 3155 | ;; Find the settings file. | ||
| 3156 | (let ((settings (project-find-settings-file (buffer-file-name))) | ||
| 3157 | (class nil) | ||
| 3158 | (root-dir nil)) | ||
| 3159 | (cond | ||
| 3160 | ((stringp settings) | ||
| 3161 | (setq root-dir (file-name-directory (buffer-file-name))) | ||
| 3162 | (setq class (project-define-from-project-file settings))) | ||
| 3163 | ((consp settings) | ||
| 3164 | (setq root-dir (car settings)) | ||
| 3165 | (setq class (cdr settings)))) | ||
| 3166 | (when class | ||
| 3167 | (let ((bindings | ||
| 3168 | (project-collect-binding-list (project-get-alist class) | ||
| 3169 | root-dir nil))) | ||
| 3170 | (when bindings | ||
| 3171 | (hack-local-variables-apply bindings root-dir) | ||
| 3172 | ;; Special case C and derived modes. Note that CC-based | ||
| 3173 | ;; modes don't work with derived-mode-p. In general I | ||
| 3174 | ;; think modes could use an auxiliary method which is | ||
| 3175 | ;; called after local variables are hacked. | ||
| 3176 | (and (boundp 'c-buffer-is-cc-mode) | ||
| 3177 | c-buffer-is-cc-mode | ||
| 3178 | (c-postprocess-file-styles)))))))) | ||
| 3007 | 3179 | ||
| 3008 | 3180 | ||
| 3009 | (defcustom change-major-mode-with-file-name t | 3181 | (defcustom change-major-mode-with-file-name t |