MBH
MBH

Reputation: 141

Emacs function returns Symbol's value as variable is void:

I am fairly new to Emacs but I know enough to be dangerous. I've built my .emacs file from scratch and now have it in an org file. I am now trying to take it to the next level and make my configuration more user friendly for myself.

I mostly use Emacs for writing. Books, blogs, screenwriting, etc. I am trying to create a function that will turn on multiple modes and add the settings on the fly.

For example, I use olivetti-mode when writing. It centers the text. Each time I have to adjust the olivetti-set-width. I thought I would get fancy and enable the spell checker and turn off linum-mode as well.

However, every time I try it I get the error:

Symbol's value as variable is void: my-writing 

Can anyone explain what I am doing wrong? I've google-fu'd quite a bit but I clearly have a gap in my understanding of what I am doing.

#+BEGIN_SRC emacs-lisp
(defun my-writing ()
"Start olivetti mode, set the width to 120, turn on spell-check."
((interactive)
 (olivetti-mode)
 (setq olivetti-set-width . 120)
 (flyspell-mode)
 (global-linum-mode 0)))

(add-hook 'olivetti-mode-hook 
    (lambda () olivetti-mode my-writing t))

#+END_SRC

Upvotes: 1

Views: 2708

Answers (2)

lawlist
lawlist

Reputation: 13467

To disable global-linum-mode for specific major-modes, see automatically disable a global minor mode for a specific major mode

[Inasmuch as olivetti-mode is a minor-mode that is enabled subsequent to whatever major-mode is already present in the buffer, the original poster may wish to turn off linum-mode locally in the current buffer by adding (linum-mode -1) to the tail end of the function my-writing (see below). That idea, however, assumes that the original poster wanted to have linum-mode active in the current buffer just prior to calling my-writing.]

The function my-writing in the initial question contains an extra set of parenthesis that should be omitted, and the hook setting is not in proper form.

olivetti-set-width is a function that takes one argument, so you cannot use setq -- see function beginning at line 197: https://github.com/rnkn/olivetti/blob/master/olivetti.el setq is used when setting a variable, not a function.

Although flyspell-mode is generally buffer-local, it is a good idea to get in the habit of using an argument of 1 to turn on a minor-mode or a -1 or 0 to turn it off. When an argument is omitted, calling the minor-mode works as an on/off toggle.

Unless there are other items already attached to the olivetti-mode-hook that require prioritization or special reasons for using a hook with buffer-local settings, you do not need the optional arguments for add-hook -- i.e., APPEND and LOCAL.

There is no apparent reason to call (olivetti-mode) as part of the olivetti-mode-hook that gets called automatically at the tail end of initializing the minor-mode, so there is now a check to see whether that mode has already been enabled. The olivetti-mode-hook is being included in this example to demonstrate how to format its usage. However, the original poster should consider eliminating (add-hook 'olivetti-mode-hook 'my-writing) as it appears to serve no purpose if the user will be calling M-x my-writing instead of M-x olivetti-mode. The hook would be useful in the latter circumstance -- i.e., when typing M-x olivetti-mode -- in which case, there is really no need to have (unless olivetti-mode (olivetti-mode 1)) as part of my-writing.

#+BEGIN_SRC emacs-lisp
(defun my-writing ()
"Start olivetti mode, set the width to 120, turn on spell-check."
(interactive)
  (unless olivetti-mode (olivetti-mode 1))
  (linum-mode -1) ;; see comments above
  (olivetti-set-width 120)
  (flyspell-mode 1))

;; original poster to consider eliminating this hook
(add-hook 'olivetti-mode-hook 'my-writing)

#+END_SRC

Upvotes: 2

Joshua Taylor
Joshua Taylor

Reputation: 85913

lawlist's answer describes how you can go about doing what you're actually trying to accomplish, but the particular error you're getting is because Emacs Lisp (like Common Lisp, but not Scheme) is a Lisp-2. When you associate a symbol with a function using defun, it doesn't make the value of that symbol (as a variable) that function, it makes the function value of that symbol the function. You'll get the same error in a much simplified situation:

(defun foo ()
  42)

(list foo)

The symbol foo has no value here as a variable. To get something that you could later pass to funcall or apply, you need to either use the symbol foo, e.g.:

(funcall 'foo)
;=> 42

or the form (function foo):

(funcall (function foo))
;=> 42

which can be abbreviated with the shorthand #':

(funcall #'foo)
;=> 42

You're getting the error because of:

(add-hook 'olivetti-mode-hook 
    (lambda () olivetti-mode my-writing t))

which tries to use my-writing as a variable, but it has no variable value at that point.

Upvotes: 2

Related Questions