0

I'm trying to set up a custom battery indicator in the mode line and I'd like to use the battery-status-function variable defined in battery.el, which is a part of emacs. However, I cannot use it in any elisp config. I have to search for it using the describe-variable function first before the value is available.

For right now, I've gotten around this by setting up a timer that runs 30 seconds after I load emacs (and once a minute afterwards) to use the battery-status-function variable. That gives me 30 seconds to search for it using describe-variable, then the battery indicator shows up in the mode line.

The problem exists even in quiet mode and both emacs 26 and 27. 26 is from the official Ubuntu package and 27 is built from source. I'm using Ubuntu 20.04 on an HP Pavillion laptop.

I can reproduce this by using eval-expression (M-:) and trying to just evaluate the battery-status-function variable. Before I look it up using describe-variable, it results in an error:

Debugger entered--Lisp error: (void-variable battery-status-function)
  eval(battery-status-function nil)
  eval-expression(battery-status-function nil nil 127)
  funcall-interactively(eval-expression battery-status-function nil nil 127)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)

After looking it up, it returns 'battery-linux-sysfs'

Has anyone run into a similar problem? What could be causing this? The variable is void until I look up the documentation on it. It's like quantum mechanics.

You might be thinking, 'just hard code "battery-linux-sysfs" into the elisp config,' but, of course, the same behavior exists for the battery-linux-sysfs function:

Debugger entered--Lisp error: (void-function battery-linux-sysfs)
  (battery-linux-sysfs)
  eval((battery-linux-sysfs) nil)
  eval-expression((battery-linux-sysfs) nil nil 127)
  funcall-interactively(eval-expression (battery-linux-sysfs) nil nil 127)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)

After looking up documentation on battery-linux-sysfs, evaluating it again returns the information about the battery as expected.

3
  • You are digging into the internals of the implementation: assuming that you've loaded the library somehow, all you need to do is call the battery function: (battery).
    – NickD
    Mar 6, 2021 at 14:15
  • Yup that's exactly it, I just didn't know to require the battery library. I was building the indicator so I was using describe functions a lot and everything worked perfectly, until I restarted emacs. It gave me the void variable error so I looked it up again thinking it was a typo, but the act of looking up documentation fixed the bug by requiring the library. Kind of a catch 22. Mar 6, 2021 at 17:22

1 Answer 1

0

I'm guessing you are missing something very fundamental here.

These lines works for me. Please let me know if it works for you.

(require 'battery)

(funcall battery-status-function)
(funcall 'battery-linux-sysfs)

NOTICE

Notice the two funcalls here, the argument is with/without ', which makes a big difference.

Should one delete the ' in the last line, one would get void-variable error like this:

Debugger entered--Lisp error: (void-variable battery-linux-sysfs)
  (funcall battery-linux-sysfs)
  elisp--eval-last-sexp(nil)
  #<subr eval-last-sexp>(nil)
  #f(compiled-function (&rest _it) #<bytecode 0x1f5e73ebdca2>)()
  eval-sexp-fu-flash-doit-simple(#f(compiled-function (&rest _it) #<bytecode 0x1f5e73ebdca2>) #f(compiled-function (&rest args2) #<bytecode -0x1f1ff2225cb0df3e>) #f(compiled-function (&rest args2) #<bytecode -0x1fdd06e42681df3e>))
  eval-sexp-fu-flash-doit(#f(compiled-function (&rest _it) #<bytecode 0x1f5e73ebdca2>) #f(compiled-function (&rest args2) #<bytecode -0x1f1ff2225cb0df3e>) #f(compiled-function (&rest args2) #<bytecode -0x1fdd06e42681df3e>))
  esf-flash-doit(#f(compiled-function (&rest _it) #<bytecode 0x1f5e73ebdca2>) #f(compiled-function (&rest args2) #<bytecode -0x1f1ff2225cb0df3e>) #f(compiled-function (&rest args2) #<bytecode -0x1fdd06e42681df3e>) #f(compiled-function (&rest args2) #<bytecode 0xc9c23271d2480c3>))
  ad-Advice-eval-last-sexp(#<subr eval-last-sexp> nil)
  apply(ad-Advice-eval-last-sexp #<subr eval-last-sexp> nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  command-execute(eval-last-sexp)

When without quote, the symbol battery-linux-sysfs will first be evaluated as a variable (not a function), which is void.

This is related to the fact that: an elisp symbol can hold a variable and a function at the same time. Refer to info for more details.

1
  • I was just missing (require 'battery). Thanks Mar 6, 2021 at 14:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.