Subject: 23.1.50; c-file-style in buffer local variables does not work!

From: Jamie Lokier <[email-masked]>
Date: Sat, 15 Aug 2009 04:41:12 +0100

Hi,

In GNU Emacs 23.1.50.1 (i486-pc-linux-gnu, GTK+ Version 2.16.1)
 of 2009-07-31 on lansones, modified by Debian
 (emacs-snapshot package, version 1:20090730-1~jaunty1)
 (= the Ubuntu-PPA Jaunty package at the time of writing)

In theory, if you put this at the top of a file, you'd expect C
indentation style to be Linux style instead of the default GNU style
(it's just an example):

-*- c-file-style: "linux" -*-

I have just opened a fresh new emacs-23.1.50.1 with "emacs -Q -nw"
and then opened a file called foo.c containing that line.

What I found is that the variable c-file-style is set to "linux" and
is buffer-local, but it does not have the effect of setting the C
indentation style.

This is the output of C-h v c-file-style RET from that buffer:

    c-file-style is a variable defined in `cc-vars.el'.
    Its value is "linux"
    Local in buffer foo.c; global value is nil

      Automatically becomes buffer-local when set in any fashion.
      This variable is a file local variable.
      This variable is safe as a file local variable if its value
      satisfies the predicate `string-or-null-p'.

The problem is that the variable is set correctly, but the intended
effect of setting the C indentation style does not happen.

I found this originally when I attempted to set a .dir-locals.el file
for a project, exactly the way it is documented in the Emacs manual
under "Per-Directory Local Variables":

     ((nil . ((indent-tabs-mode . t)
              (tab-width . 8)
              (fill-column . 79)))
      (c-mode . ((c-file-style . "linux"))))

It turns out that doesn't work either, and then I confirmed it has the
same problem when c-file-style is file-local.

A bit of debugging reveals that this is called from cc-mode.el.gz,
when the file-local variable is set:

    (c-set-style "GNU" t)
    (c-set-style "linux" t)

So c-file-style does trigger a call to c-set-style.

Trouble is, that third argument t means "don't override settings
already set", and they were already set by the first call.  The first
call always happens, and it sets the default style.

Fortunately I found a workaround in my .dir-locals.el file that does
not ask questions:

    ((c-mode . ((eval . (c-set-style "linux")))))

Since the entire purpose of c-file-style is to do exactly this, and
since it's documented in both the Emacs manual as well as the CC Mode
manual, it's clear that it's broken.

All this is with "emacs -Q": no customisations.

Thanks,
-- Jamie