How to call interactive Emacs Lisp function with a prefix argument, from another Emacs Lisp function? - emacs

I want to write an Emacs Lisp function that will turn on flyspell-mode regardless of the current state of the mode. Function flyspell-mode-on is deprecated. The documentation suggests that a positive prefix argument will turn flyspell-mode, but unfortunately running
(flyspell-mode 1)
results in an error message:
Wrong number of arguments: (lambda (flyspell-mode 1)), 0
If I could figure out how to call flyspell-mode with a prefix argument, I believe I could solve this problem.
The most relevant section I can find in the Emacs Lisp manual is the section entitled "Interactive Call", which describes such commands as call-interactively. This is emphatically not what I want.
(The ultimate problem I am trying to solve is to create a mode hook that turns on the mode regardless of its current state.)
N.B. The title of the question emacs lisp call function with prefix argument programmatically makes it appear to be related, but that question was asking about how to create an interactive command, and the issue was ultimately resolved by using call-interactively.
EDIT: This question is moot; I have found an alternate solution to my original problem:
(add-hook 'text-mode-hook
(function (lambda ()
(require 'flyspell)
(if flyspell-mode nil (flyspell-mode)))))
But I would still like to know how to call an Emacs Lisp function with a prefix argument, from another Emacs Lisp function, with nothing interactive.
UPDATE: Perhaps I should have asked why I was getting that error message...

It looks like your version of Flyspell mode does not follow the minor mode conventions, which require that you can turn on a minor mode with (name-of-mode t) or any positive prefix argument, turn it off with (name-of-mode 0) any negative prefix argument, and toggle it with (name-of-mode nil).
If you have the latest version of Flyspell, a bug report might be in order. I have the version shipped with GNU Emacs 23.2 on my machine, and it respects the convention. My version also defines two functions turn-on-flyspell and turn-off-flyspell, both trivial wrappers around flyspell-mode; functions with such names are common, but not official conventions. The functions flyspell-mode-on and flyspell-mode-off are apparently intended for internal use.
As a general matter, commands read the current prefix argument from the current-prefix-arg variable. Don't confuse that with prefix-arg, which is the value for the next command (only a few commands like universal-argument touch this variable). Thus, if you need to pass a prefix argument when calling a function, bind or set current-prefix-arg.
(let ((current-prefix-arg t))
(flyspell-mode))

If you are not calling a function interactively, then the (interactive) declaration is not used to obtain the arguments.
In the vast majority of cases, you do not need to worry about whether an argument can be a "prefix argument" for non-interactive calls; just check the function documentation, and pass the value you need for whatever it is you want to do.
If for some reason you do need to replicate sending a prefix argument in a non-interactive context, you will need to check that function's (interactive) declaration and determine exactly how it is using that argument, and ensure that you replicate that behaviour for the argument you do pass.
For full details, see:
C-hf interactive RET
M-: (info "(elisp) Prefix Command Arguments") RET
In more complex cases where the function changes its behaviour based on the current-prefix-arg variable, you may be able to set that variable directly.
(let ((current-prefix-arg '(4)))
(foo current-prefix-arg))

I can think of this.. Should be more better
(call-interactively (lambda ()
(interactive)
(flyspell-mode '(4))))
UPDATE:
I can run this directly.. what am i missing from the question.?
(flyspell-mode '(4))
EDITED: Removed quote for lambda expression (I added this note because SX forces an edit to be at least six characters long, so this can be deleted).

FWIW, the `flyspell-mode' function has accepted an argument (as in "(flyspell-mode 1)") at least since Emacs-21, so I don't know how you got that error.
But while I'm here, I might as well point out that (add-hook 'text-mode-hook 'flyspell-mode) has changed meaning in Emacs-24: instead of meaning "toggle flyspell-mode in text modes" it will now mean "enable flyspell-mode in text modes". It's a backward-incompatible change, but I believe it will fix more latent bugs than it will introduce.

See my comment for the fix to the source of your problem. As for the answer to your question, the way the prefix arg is turned into some kind of Lisp argument depends on the interactive spec, so the only way to do it reliably (i.e. without prior knowledge such as the fact that it's a minor mode function) is to call the function interactively:
(let ((current-prefix-arg '(4)))
(call-interactively 'flyspell-mode))

I'm not Emacs and Elisp master (yet ;)) but I think in this case you may use Ctrl-u 1 Alt-x flyspell-mode.

Related

indent-[code-]rigidly called from emacs LISP function

I'm trying to write an emacs LISP function to un-indent the region
(rigidly). I can pass prefix arguments to indent-code-rigidly or
indent-rigidly or indent-region and they all work fine, but I don't
want to always have to pass a negative prefix argument to shift things
left.
My current code is as below but it seems to do nothing:
(defun undent ()
"un-indent rigidly."
(interactive)
(list
(setq fline (line-number-at-pos (region-beginning)))
(setq lline (line-number-at-pos (region-end)))
(setq curIndent (current-indentation))
;;(indent-rigidly fline lline (- curIndent 1))
(indent-region fline lline 2)
;;(message "%d %d" curIndent (- curIndent 1))
)
)
I gather that (current-indentation) won't get me the indentation of the first line
of the region, but of the first line following the region (so a second quesiton is
how to get that!). But even when I just use a constant for the column (as shown,
I don't see this function do any change.
Though if I uncomment the (message) call, it displays reasonable numbers.
GNU Emacs 24.3.1, on Ubuntu. And in case it matters, I use
(setq-default indent-tabs-mode nil) and (cua-mode).
I must be missing something obvious... ?
All of what Tim X said is true, but if you just need something that works, or an example to show you what direction to take your own code, I think you're looking for something like this:
(defun unindent-rigidly (start end arg &optional interactive)
"As `indent-rigidly', but reversed."
(interactive "r\np\np")
(indent-rigidly start end (- arg) interactive))
All this does is call indent-rigidly with an appropriately transformed prefix argument. If you call this with a prefix argument n, it will act as if you had called indent-rigidly with the argument -n. If you omit the prefix argument, it will behave as if you called indent-rigidly with the argument -1 (instead of going into indent-rigidly's interactive mode).
There are a number of problems with your function, including some vary
fundamental elisp requirements. Highly recommend reading the Emacs Lisp
Reference Manual (bundled with emacs). If you are new to programming and lisp,
you may also find An Introduction to Emacs Lisp useful (also bundled with
Emacs).
A few things to read about which will probably help
Read the section on the command loop from the elisp reference. In particular,
look at the node which describes how to define a new command and the use of
'interactive', which you will need if you want to bind your function to a key
or call it with M-x.
Read the section on variables from the lisp reference
and understand variable scope (local v global). Look at using 'let' rather
than 'setq' and what the difference is.
Read the section on 'positions' in the elisp reference. In particular, look at
'save-excursion' and 'save-restriction'. Understanding how to define and use
the region is also important.
It isn't clear if your writing this function just as a learning exercise or
not. However, just in case you are doing it because it is something you need to
do rather than just something to learn elisp, be sure to go through the Emacs
manual and index. What you appear to need is a common and fairly well supported
requirement. It can get a little complicated if programming modes are involved
(as opposed to plain text). However, with emacs, if what you need seems like
something which would be a common requirement, you can be fairly confident it is
already there - you just need to find it (which can be a challenge at first).
A common convention is for functions/commands to be defined which act 'in
reverse' when supplied with a negative or universal argument. Any command which
has this ability can also be called as a function in elisp code with the
argument necessary to get that behaviour, so understanding the inter-play
between commands, functions and calling conventions is important.

What is the difference between using "setq" or not to set an Emacs setting?

Very simple question but confuse me for some time:
(setq visible-bell t)
and
(visible-bell t)
both seem work.
But
(desktop-save-mode 1)
works, while
(setq desktop-save-mode 1)
not.
May I ask why is this?
They're different because they're different :)
(setq visible-bell t)
is assigning the value t to a variable named visible-bell.
(visible-bell t)
is calling a function1 named visible-bell (and passing the value t as a parameter).
(Although FYI there is no visible-bell function by default in current versions of Emacs, so it's not obvious to me that this is actually working the way you think? However, assuming for the moment that you do indeed have such a function...)
Emacs Lisp is a 'Lisp-2' meaning it has separate name spaces for variables and functions, and therefore you can -- and commonly do -- have a variable and a function with the same name. Which one is being referred to is always implicit in the context of the code (e.g. setq always refers to a variable).
In short, the two pieces of code are doing very different things. This doesn't mean they couldn't have an equivalent effect (e.g. the function might simply set the value of the variable); but whether or not that's actually the case is entirely up to the definition of the function.
1 In fact the first line of code is also calling a function2: it's calling setq and passing it two parameters visible-bell and t, and setq then sets the value in accordance with its parameters. Hopefully you're now starting to see how lisp syntax works?
2 Strictly speaking, setq is actually a "special form" rather than a function, and special forms are closer to macros than to functions; but these distinctions are not important for this Q&A.
Others have told you the basic points about what setq does and about variables versus functions.
Wrt visible-bell itself:
There is no function visible-bell delivered with Emacs, in any Emacs version I know of, and there never has been. (I've checked back through Emacs 20, and by memory I believe the same was true from the beginning. There is only the variable visible-bell.
So as #phils suggested, is not clear that what you said is true: "both seem to work". Unless some extra code you are loading defines a function of that name (and then there is no way for us to comment on it, not having it to see), evaluating (visible-bell t) raises an undefined (void) function error.
Variable visible-bell is not just a variable. It is a user option, and it has been, again, since at least Emacs 20.
You should not, in general, just use setq to change the value of a user option. In many cases you won't get into trouble if you do that, but sometimes you will, and it is not a good habit to get into.
setq does not perform any special initialization or updating actions that might be appropriate for a given user option. It is not intended for user options. Or rather, user options are not intended for setq - they can be more complex than what setq can offer.
What you should use instead of setq is Customize. Either interactively (M-x customize-option RET visible-bell RET, or C-h v RET visible-bell RET followed by clicking the customize link) or using Lisp code in your init file.
If you use Lisp code then use one of these functions (not setq):
customize-set-variable
customize-set-value
custom-set-variables
Use C-h f followed by each of those function names, to see what (minor) differences there are.
There are 3 issues here.
In Emacs Lisp, the same symbol can be both variable and function.
in the case of desktop-save-mode, it's a function but also a variable.
Because it's a function, so you can call
(desktop-save-mode 1)
Because it's a variable, so you set value to it
(setq desktop-save-mode t)
You can define your own function and also a variable of the same name to test it.
Note: exactly what a function's arguments should be or what the value of a variable makes sense depends on the function or variable.
Now, a second issue. In general, for function (commands) to activate a minor mode, the convention is that a positive integer should mean to turn it on, and otherwise turn off.
Also, for command to activate a minor mode, typically there's a variable of the same name, with value of t or nil, to indicate if the mode is on.
Now, there's third issue. For command to activate the mode, before emacs 24 or so, by convention, if no arg is given, the command toggle current state.
Because all of the above, the issue is confusing. You might see in init things like this:
(desktop-save-mode 1) ; correct. To turn on.
(desktop-save-mode) ; Confusing. Should take value 1 to turn on. Usually works because by default it's off.
(desktop-save-mode t) ; wrong. Take value of positive integer to turn on.
(desktop-save-mode nil) ; Confusing. Value should be integer
(setq desktop-save-mode t) ; wrong. Shoud call function instead
(setq desktop-save-mode nil) ; wrong. Shoud call function instead
(setq desktop-save-mode 1) ; wrong. Shoud call function instead. Besides, only t and nil make sense
So, there's a lot confusion. In emacs 24 (or 23.x), the convention changed so that, if it receives no value, it will turn on, if called in elisp code. (when called interactively as command, it toggles.)
In the end, always call describe-function or describe-variable to read the doc.
Well setq (which is "set" with an auto-quoting feature) is used in assigning a value to a variable. In this example, it's obviously not required because as you mentioned, omitting it works for the first set of examples.
Basically, visible-bell is a variable, and you assign it the value "t" to enable visible bells.
However, desktop-save-mode is an interactive function, so you don't use setq to assign it a value, you call it with parameters.
One good thing to do when you're not sure what something is, is to use the built-in help function:
C-h v visible-bell RET
This will return the information for visible bell -- notice the "v" in the command is because it's a variable. If you wanted to search for information on a function, you would do this:
C-h f desktop-save-mode RET
Incidentally in this case, desktop-save-mode is also a variable, but it's a read-only variable to determine whether or not desktop-save-mode is enabled, so trying to alter it will not work.

How to remove "Toggling multi-web-mode off; better pass an explicit argument" message in Emacs?

I have noticed, from a while, that every time I run emacs in multi-web-mode I get the following message:"Toggling multi-web-mode off; better pass an explicit argument".
Why do I get that? multi-web-mode is not toggled off because I use it and it works fine, but I keep getting this message all the time.
How can I fix this little trouble?
This is my code in my .emacs file where "multi-web-mode" appears (I am using Emacs 23.4):
(require 'multi-web-mode)
(setq mweb-default-major-mode 'html-mode)
(setq mweb-tags '((c++-mode "<\\?php\\|<\\? \\|<\\?=" "\\?>")
(ecmascript-mode "<script +\\(type=\"text/javascript\"\\|language=\"javascript\"\\)[^>]*>" "</script>")
(css-mode "<style +type=\"text/css\"[^>]*>" "</style>")))
(setq mweb-filename-extensions '("php" "htm" "html" "ctp" "phtml" "php4" "php5"))
(multi-web-global-mode 1)
(add-to-list 'auto-mode-alist '("\\.php\\'" . multi-web-mode))
(add-to-list 'auto-mode-alist '("\\.html\\'" . multi-web-mode))
Well it sounds like somewhere there's some code causing this mode to be called, non-interactively, with no arguments: (multi-web-mode). A common cause would be specifying a mode function symbol for use as a callback, rather than specifying a function which will call that mode function (with an argument).
This certainly used to be bad form, as it would indeed act as a toggle, just as it does in the interactive case (e.g. M-x multi-web-mode). Since Emacs 24, however, it is actually safe to do (at least for modes defined with the standard macros), as a non-interactive call with no argument to a mode function now always means 'enable'. This might account for the fact that you're not actually seeing a problem.
I don't think stock Emacs has ever generated such a message, so I would presume it's multi-web-mode itself which is detecting and reporting on this. It may need to be updated to reflect the change in Emacs 24. (Edit: looks like I was wrong about that; I guess Emacs 23.4 did produce this warning.)
Your simplest fix is probably to show us any lines from your config which mention multi-web-mode, so someone can show you how to change it to ensure that it passes an explicit argument (which is typically 1 to enable a mode).
Edit: Okay, your problem is that multi-web-mode is a minor mode (as opposed to a major mode), but you have specified it in auto-mode-alist which is a mechanism for mapping filename patterns to major modes.
So the cause is exactly as I suggested above when I said "A common cause would be specifying a mode function symbol for use as a callback", as those auto-mode-alist entries will result in a call to (multi-web-mode).
It appears to me that multi-web-global-mode handles enabling the minor mode as required, so you just need to remove the bad auto-mode-alist entries.

How to keep dir-local variables when switching major modes?

I'm committing to a project where standard indentations and tabs are 3-chars wide, and it's using a mix of HTML, PHP, and JavaScript. Since I use Emacs for everything, and only want the 3-char indentation for this project, I set up a ".dir-locals.el" file at the root of the project to apply to all files/all modes under it:
; Match projets's default indent of 3 spaces per level- and don't add tabs
(
(nil .
(
(tab-width . 3)
(c-basic-offset . 3)
(indent-tabs-mode . nil)
))
)
Which works fine when I first open a file. The problem happens when switching major modes- for example to work on a chunk of literal HTML inside of a PHP file. Then I lose all the dir-local variables.
I've also tried explicitly stating all of the modes I use in ".dir-locals.el", and adding to my .emacs file "dir-locals-set-class-variables / dir-locals-set-directory-class". I'm glad to say they all behave consistently, initially setting the dir-local variables, and then losing them as I switch the major mode.
I'm using GNU Emacs 24.3.1.
What's an elegant way of reloading dir-local variables upon switching a buffer's major-mode?
-- edit -- Thanks for the excellent answers and commentary both Aaron and phils! After posting here, I thought it "smelled" like a bug, so entered a report to GNU- will send them a reference to these discussions.
As per comments to Aaron Miller's answer, here is an overview of what happens when a mode function is called (with an explanation of derived modes); how calling a mode manually differs from Emacs calling it automatically; and where after-change-major-mode-hook and hack-local-variables fit into this, in the context of the following suggested code:
(add-hook 'after-change-major-mode-hook 'hack-local-variables)
After visiting a file, Emacs calls normal-mode which "establishes the proper major mode and buffer-local variable bindings" for the buffer. It does this by first calling set-auto-mode, and immediately afterwards calling hack-local-variables, which determines all the directory-local and file-local variables for the buffer, and sets their values accordingly.
For details of how set-auto-mode chooses the mode to call, see C-hig (elisp) Auto Major Mode RET. It actually involves some early local-variable interaction (it needs to check for a mode variable, so there's a specific look-up for that which happens before the mode is set), but the 'proper' local variable processing happens afterwards.
When the selected mode function is actually called, there's a clever sequence of events which is worth detailing. This requires us to understand a little about "derived modes" and "delayed mode hooks"...
Derived modes, and mode hooks
The majority of major modes are defined with the macro define-derived-mode. (Of course there's nothing stopping you from simply writing (defun foo-mode ...) and doing whatever you want; but if you want to ensure that your major mode plays nicely with the rest of Emacs, you'll use the standard macros.)
When you define a derived mode, you must specify the parent mode which it derives from. If the mode has no logical parent, you still use this macro to define it (in order to get all the standard benefits), and you simply specify nil for the parent. Alternatively you could specify fundamental-mode as the parent, as the effect is much the same as for nil, as we shall see momentarily.
define-derived-mode then defines the mode function for you using a standard template, and the very first thing that happens when the mode function is called is:
(delay-mode-hooks
(PARENT-MODE)
,#body
...)
or if no parent is set:
(delay-mode-hooks
(kill-all-local-variables)
,#body
...)
As fundamental-mode itself calls (kill-all-local-variables) and then immediately returns when called in this situation, the effect of specifying it as the parent is equivalent to if the parent were nil.
Note that kill-all-local-variables runs change-major-mode-hook before doing anything else, so that will be the first hook which is run during this whole sequence (and it happens while the previous major mode is still active, before any of the code for the new mode has been evaluated).
So that's the first thing that happens. The very last thing that the mode function does is to call (run-mode-hooks MODE-HOOK) for its own MODE-HOOK variable (this variable name is literally the mode function's symbol name with a -hook suffix).
So if we consider a mode named child-mode which is derived from parent-mode which is derived from grandparent-mode, the whole chain of events when we call (child-mode) looks something like this:
(delay-mode-hooks
(delay-mode-hooks
(delay-mode-hooks
(kill-all-local-variables) ;; runs change-major-mode-hook
,#grandparent-body)
(run-mode-hooks 'grandparent-mode-hook)
,#parent-body)
(run-mode-hooks 'parent-mode-hook)
,#child-body)
(run-mode-hooks 'child-mode-hook)
What does delay-mode-hooks do? It simply binds the variable delay-mode-hooks, which is checked by run-mode-hooks. When this variable is non-nil, run-mode-hooks just pushes its argument onto a list of hooks to be run at some future time, and returns immediately.
Only when delay-mode-hooks is nil will run-mode-hooks actually run the hooks. In the above example, this is not until (run-mode-hooks 'child-mode-hook) is called.
For the general case of (run-mode-hooks HOOKS), the following hooks run in sequence:
change-major-mode-after-body-hook
delayed-mode-hooks (in the sequence in which they would otherwise have run)
HOOKS (being the argument to run-mode-hooks)
after-change-major-mode-hook
So when we call (child-mode), the full sequence is:
(run-hooks 'change-major-mode-hook) ;; actually the first thing done by
(kill-all-local-variables) ;; <-- this function
,#grandparent-body
,#parent-body
,#child-body
(run-hooks 'change-major-mode-after-body-hook)
(run-hooks 'grandparent-mode-hook)
(run-hooks 'parent-mode-hook)
(run-hooks 'child-mode-hook)
(run-hooks 'after-change-major-mode-hook)
Back to local variables...
Which brings us back to after-change-major-mode-hook and using it to call hack-local-variables:
(add-hook 'after-change-major-mode-hook 'hack-local-variables)
We can now see clearly that if we do this, there are two possible sequences of note:
We manually change to foo-mode:
(foo-mode)
=> (kill-all-local-variables)
=> [...]
=> (run-hooks 'after-change-major-mode-hook)
=> (hack-local-variables)
We visit a file for which foo-mode is the automatic choice:
(normal-mode)
=> (set-auto-mode)
=> (foo-mode)
=> (kill-all-local-variables)
=> [...]
=> (run-hooks 'after-change-major-mode-hook)
=> (hack-local-variables)
=> (hack-local-variables)
Is it a problem that hack-local-variables runs twice? Maybe, maybe not. At minimum it's slightly inefficient, but that's probably not a significant concern for most people. For me, the main thing is that I wouldn't want to rely upon this arrangement always being fine in all situations, as it's certainly not the expected behaviour.
(Personally I do actually cause this to happen in certain specific cases, and it works just fine; but of course those cases are easily tested -- whereas doing this as standard means that all cases are affected, and testing is impractical.)
So I would propose a small tweak to the technique, so that our additional call to the function does not happen if normal-mode is executing:
(defvar my-hack-local-variables-after-major-mode-change t
"Whether to process local variables after a major mode change.
Disabled by advice if the mode change is triggered by `normal-mode',
as local variables are processed automatically in that instance.")
(defadvice normal-mode (around my-do-not-hack-local-variables-twice)
"Prevents `after-change-major-mode-hook' from processing local variables.
See `my-after-change-major-mode-hack-local-variables'."
(let ((my-hack-local-variables-after-major-mode-change nil))
ad-do-it))
(ad-activate 'normal-mode)
(add-hook 'after-change-major-mode-hook
'my-after-change-major-mode-hack-local-variables)
(defun my-after-change-major-mode-hack-local-variables ()
"Callback function for `after-change-major-mode-hook'."
(when my-hack-local-variables-after-major-mode-change
(hack-local-variables)))
Disadvantages to this?
The major one is that you can no longer change the mode of a buffer which sets its major mode using a local variable. Or rather, it will be changed back immediately as a result of the local variable processing.
That's not impossible to overcome, but I'm going to call it out of scope for the moment :)
Be warned that I have not tried this, so it may produce undesired results ranging from your dir-local variables not being applied, to Emacs attempting to strangle your cat; by any sensible definition of how Emacs should behave, this is almost certainly cheating. On the other hand, it's all in the standard library, so it can't be that much of a sin. (I hope.)
Evaluate the following:
(add-hook 'after-change-major-mode-hook
'hack-dir-local-variables-non-file-buffer)
From then on, when you change major modes, dir-local variables should (I think) be reapplied immediately after the change.
If it doesn't work or you don't like it, you can undo it without restarting Emacs by replacing 'add-hook' with 'remove-hook' and evaluating the form again.
My take on this:
(add-hook 'after-change-major-mode-hook #'hack-local-variables)
and either
(defun my-normal-mode-advice
(function &rest ...)
(let ((after-change-major-mode-hook
(remq #'hack-local-variables after-change-major-mode-hook)))
(apply function ...)))
if you can live with the annoying
Making after-change-major-mode-hook buffer-local while locally let-bound!
message or
(defun my-normal-mode-advice
(function &rest ...)
(remove-hook 'after-change-major-mode-hook #'hack-local-variables)
(unwind-protect
(apply function ...)
(add-hook 'after-change-major-mode-hook #'hack-local-variables)))
otherwise and finally
(advice-add #'normal-mode :around #'my-normal-mode-advice)

Emacs Lisp: Can't set any value to variable named 's'

This is rather queer. I can't set any value to a variable if it is named 's' in an interactive session:
(setq s 'foo)
=> foo
s
=> nil
Why?
Update 1:
Here is the output from describe-variable on s:
s is void as a variable.
Documentation:
Not documented as a variable.
Why is it that s is kept void in emacs lisp as a global variable?
Update 2:
Turned out, it doesn't happen on a vanilla emacs (meaning one of the modules I load in .emacs or some code in .emacs is causing this).
So the question now is:
What would the original source look like when describe-variable yields "<var> is void as a variable"?
I tried it with setq, defconst, defvar, and defcustom, but none of those produced the message I'm showing.
Update 3:
The message shown above is produced when the variable is literally not bound (though it can be fbound).
(describe-variable 'non-existent)
=> "non-existent is void as a variable.
Documentation:
Not documented as a variable."
So latest question is: Is there any way to prevent a certain variable name
from being bound?
An answer to your revised question:
(defvar s)
The only thing is that this won't let you use describe-variable on it interactively.
(You could then do something like (setplist 's '(variable-documentation "Meh")) to set a description for it without going through defvar.
Just bisect your init file (~/.emacs) recursively until you find the sexp that causes the problem. If it is a sexp that loads another library then either don't use that library or fix it by first finding out what its problem is, the same way: bisect the code in that library recursively, etc.
This is a binary search, and it is very quick. You can quickly comment out half, then 3/4, 7/8, etc. of your file, using M-x comment-region (I bind it to C-x ;). with a prefix arg, comment-region uncomments.
With Emacs 23.1, running the following code makes C-h v s RET show “s is void as a variable.”, but I can't reproduce the inconsistency between setq and retrieving the value of the variable (which I agree is weird).
(setq s t)
(make-local-variable 's)
(makunbound 's)
I suspect an Emacs 24-specific feature or bug.