How to call a function in a user defined function im Emacs? - emacs

I use defun to define a function in my .emacs file:
(defun myfun ()
"i am already loaded the color-theme lib"
(color-theme-initialize)
(color-theme-darkblue))
Then I want to use this function in my mode-hook:
(add-hook 'python-mode-hook
'(lambda ()
(myfun)
(...)))
But I got an error saying that the color-theme-initialize function is void.
P.S. my ~/.emacs snippet
(progn (require 'color-theme)
(color-theme-initialize))
(progn (setq-default indent-tabs-mode nil)
(setq-default tab-width 2)
(setq indent-line-function 'insert-tab))
(add-hook 'emacs-lisp-mode-hook
'(lambda ()
(color-theme-resolve)
(show-paren-mode t)
(linum-mode t)))

You need to require (or otherwise load) the library which provides color-theme-initialize. I'm guessing (require 'color-theme).

Read the error, it's not your function that cannot be called, but the
function named color-theme-initialize. This function has been
removed some times ago but can still be present in some older version
of color-theme. Thus, check your version of color-theme and see if
there is a function called color-theme-initialize (with
C-hfcolor-theme-initializeRET). If
the function is present then you have to (require 'color-theme),
otherwise you don't need to call this function.

Related

Set variable under specific mode emacs

Looking to set a variable under latex mode. The idea is that the value set under latex mode will override the value of the same variable set in the customise section. I am very new to emacs so these are my attempts:
(add-hook 'LaTeX-mode-hook '(setq line-move-visual t))
(add-hook 'latex-mode-hook (lambda () (setq line-move-visual t)))
Why do these not work? What should I do instead?
Clarification: looking to set the variable (setq line-move-visual t) as I have it as (setq line-move-visual nil) for all other files
If you just setq the variable in your LaTeX-mode-hook it will also have an effect on any other open buffer. It is possible to make the change only effect the current buffer:
(add-hook 'LaTeX-mode-hook
(lambda ()
(make-local-variable 'line-move-visual)
(setq line-move-visual nil)))
Also, please note that the hook for the default mode for LaTeX in Emacs is called latex-mode-hook but the hook when you are using the (far superior) AUCTeX is called LaTeX-mode-hook
EDIT: Changed make-variable-buffer-local to make-local-variable. See comments to this answer.

Emacs: use add-hook inside function (defun)

If I do
(add-hook 'haskell-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(message "OK")))
in my ~/.emacs.d/init.el, then the (lambda ...) does get executed when I enter haskell-mode.
However, if I use a function like this:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK"))))
and then call it later in ~/.emacs.d/init.el like so:
(my-add-hook 'haskell-mode-hook t 4)
Then nothing happens (even the "OK" message isn't displayed). Is add-hook a
special function that cannot be used from within a defun? I have per-project
settings defined in a separate initialization file that detects the buffer name
and adds (lambda ()...) calls to the pertinent major mode (in the example
above, haskell-mode); I want to reduce the code verbosity by using a thin
wrapper like my-add-hook above, but I cannot tell why add-hook is being so
difficult.
EDIT1: Added code for clarification.
EDIT2: I do get a "File mode specification error: (void-variable tmode)" message when I try to use my-add-hook.
Here's a simple fix without needing to know about lexical binding:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
`(lambda ()
(setq indent-tabs-mode ,tmode)
(setq tab-width ,twidth)
(message "OK"))))
You can use lexical-let to rebind the variables, then the lambda function will preserve their values:
(defun my-add-hook (hook tmode twidth)
(lexical-let ((tmode tmode)
(twidth twidth))
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK")))))
I'm not sure whether this is the most idiomatic Emacs Lisp code, but it does follow the same pattern shown in the Emacs Wiki article DynamicBindingVsLexicalBinding, which defines compose as:
(defun compose (f g)
(lexical-let ((f f)
(g g))
(lambda (x)
(funcall f (funcall g x)))))

use .dir-locals.el to pick major mode [duplicate]

I have defined a .dir-locals.el file with the following content:
((python-mode . ((cr/virtualenv-name . "saas"))))
In my .emacs I have the following function to retrieve this value and provide a virtualenv path:
(defun cr/virtualenv ()
(cond (cr/virtualenv-name (format "%s/%s" virtualenv-base cr/virtualenv-name))
((getenv "EMACS_VIRTUAL_ENV") (getenv "EMACS_VIRTUAL_ENV"))
(t "~/.emacs.d/python")))
Finally, in my python-mode-hook list, I have this hook function:
(add-hook 'python-mode-hook 'cr/python-mode-shell-setup)
(defun cr/python-mode-shell-setup ()
(message "virtualenv-name is %s" cr/virtualenv-name)
(let ((python-base (cr/virtualenv)))
(cond ((and (fboundp 'ipython-shell-hook) (file-executable-p (concat python-base "/bin/ipython")))
(setq python-python-command (concat python-base "/bin/ipython"))
(setq py-python-command (concat python-base "/bin/ipython"))
(setq py-python-command-args '( "-colors" "NoColor")))
(t
(setq python-python-command (concat python-base "/bin/python"))
(setq py-python-command (concat python-base "/bin/python"))
(setq py-python-command-args nil)))))
When I open a new python file, the message logged by cr/python-mode-shell-setup indicates that cr/virtualenv-name is nil. However, when I C-h v the name, I get "saas" instead.
Obviously there's a load order issue here; is there a way to have my mode hook statements respond to directory-local variables?
This happens because normal-mode calls (set-auto-mode) and (hack-local-variables) in that order.
However hack-local-variables-hook is run after the local variables have been processed, which enables some solutions:
The first is to make Emacs run a new "local variables hook" for each major mode:
(add-hook 'hack-local-variables-hook 'run-local-vars-mode-hook)
(defun run-local-vars-mode-hook ()
"Run a hook for the major-mode after the local variables have been processed."
(run-hooks (intern (concat (symbol-name major-mode) "-local-vars-hook"))))
(add-hook 'python-mode-local-vars-hook 'cr/python-mode-shell-setup)
(Your original function can be used unmodified, with that approach.)
A second option is to utilise the optional LOCAL argument to add-hook that makes the specified function buffer-local. With this approach you could write your hook as follows:
(add-hook 'python-mode-hook 'cr/python-mode-shell-setup)
(defun cr/python-mode-shell-setup ()
(add-hook 'hack-local-variables-hook
(lambda () (message "virtualenv-name is %s" cr/virtualenv-name)
(let ((python-base (cr/virtualenv)))
(cond ((and (fboundp 'ipython-shell-hook) (file-executable-p (concat python-base "/bin/ipython")))
(setq python-python-command (concat python-base "/bin/ipython"))
(setq py-python-command (concat python-base "/bin/ipython"))
(setq py-python-command-args '( "-colors" "NoColor")))
(t
(setq python-python-command (concat python-base "/bin/python"))
(setq py-python-command (concat python-base "/bin/python"))
(setq py-python-command-args nil)))))
nil t)) ; buffer-local hack-local-variables-hook
i.e. python-mode-hook runs first and registers the anonymous function with hack-local-variables-hook for the current buffer only; and that function is then called after the local variables have been processed.
Lindydancer's comment prompts a third approach. It's not nearly as clean as the other two, but proved interesting regardless. I didn't like the idea of causing (hack-local-variables) to be called twice, but I see that if you set the local-enable-local-variables buffer-locally, it prevents (hack-local-variables) from doing anything, so you could do this:
(defun cr/python-mode-shell-setup ()
(report-errors "File local-variables error: %s"
(hack-local-variables)))
(set (make-local-variable 'local-enable-local-variables) nil)
(let ((python-base (cr/virtualenv)))
...))
Obviously that modifies the normal sequence of execution a little, so side effects may be possible. I was worried that if the same major mode is set by a local variable comment in the file, this might cause infinite recursion, but that doesn't actually appear to be a problem.
Local variable header comments (e.g. -*- mode: foo -*-) are handled by (set-auto-mode), so those are fine; but a mode: foo Local Variables: comment seems like it would be an issue as it is handled by (hack-local-variables), and so if the mode is set that way I thought it would cause recursion.
In practice I was able to trigger the problem by using a simple function as a 'mode' which did nothing more than try to run its hooks; however testing with a 'proper' mode did not exhibit the problem, so it's probably safe in reality. I didn't look into this further (as the other two solutions are much cleaner than this), but I would guess the delayed mode hooks mechanism probably explains it?

Emacs: hooking a custom extension to a cc-mode

For my c (c++) files, I added this reference to a cc-mode to my .emacs file:
(setq c-default-style "stroustrup"
c-basic-offset 4)
I would like to use the same for a custom extension ".dec." I tried to naively adjust this SO question doing
(defun my-decaf-mode ()
(when (and (stringp buffer-file-name)
(string-match "\\.dec\\'" buffer-file-name))
(setq c-default-style "stroustrup")
(c-basic-offset 4)) )
(add-hook 'find-file-hook 'my-decaf-mode)
which didn't work (I wrote a few lines in C; the support I would get giving the file a .c extension was not there). I also tried the actual customization type as in
(setq c-default-style "stroustrup"
c-basic-offset 4)) )
How could I get this done?
This answer assumes that the function my-decaf-mode does exactly what the original poster wants, and that the only thing needed is to associate *.dec extension files with c-mode and then call the function my-decaf-mode when the major-mode c-mode is activated in a buffer:
(add-to-list 'auto-mode-alist '("\\.dec\\'" . c-mode))
(add-hook 'c-mode-hook 'my-decaf-mode)

Why are my mode specific .emacs hooks running for all modes?

I'm running the following code in my .emacs file:
(defun load-hooks ()
(add-hook 'after-save-hook 'my-hook))
(add-hook 'c-mode-hook 'load-hooks)
(defun my-hook () ... )
However, the content in my-hook is running on save even when I'm in a different mode. Am I missing a step?
You should use the LOCAL argument to add-hook, which will make sure that the hook only affects the current buffer:
(defun load-hooks ()
(add-hook 'after-save-hook 'my-hook nil t))
(add-hook 'c-mode-hook 'load-hooks)
(defun my-hook () ...)
I think that calling (add-hook 'after-save-hook 'my-hook) in load-hooks adds the hook to all modes. That is, once that function is called, after-save-hook is modified for every other buffer as well.
I suspect that your hook would not be run unless you open a c file. Try opening some file without having opened any c files and see if anything is run. If it isn't it just means that the function that runs for c files modifies the save hook for everything else.
Tikhon was correct about the 'after-save-hook affecting all modes - I am now relying on a check using the following functions:
(defun in-c-mode? ()
(string= (current-major-mode) "c-mode"))
(defun current-major-mode ()
(with-current-buffer (current-buffer) major-mode))