Controlling verbosity of byte-compilation (CL library) - emacs

When byte-compiling several eLisp files in a batch the output from the compiler is cluttered with Warning: function `position' from cl package called at runtime warnings. I understand, although don't agree that much with the policy on cl package. But this makes spotting other, more useful warnings more difficult. So, while there's no real way to avoid the warning, is there a way to selectively shut off all warnings of a certain pattern?
EDIT: (attached an example)
create file called doodles.el
(require 'cl)
(eval-when-compile (require 'cl))
(dotimes (i 1)
(position ?\x "x"))
M-x byte-compile-file RET doodles.el
Switch to *Compile-Log* buffer:
doodles.el:1:1:Warning: cl package required at runtime
this is what you get.

You can control byte-compiler warnings with a Local variables block that sets the byte-compile-warnings variable. To turn off the CL-at-runtime warning, place this near the end of your module:
;; Local Variables:
;; byte-compile-warnings: (not cl-functions)
;; End:

The warning function position from cl package called at runtime is not there because of the policy on CL (well, it does have something to do with it, admittedly) but is pointing out an actual real problem: you use position in a file which does not (require 'cl). The file probably does (eval-when-compile (require 'cl)) which means CL is available during compilation (a.g. to expand CL macros), but will not be loaded at run time.
Often this does not result in a bug, because some other file somewhere does (require 'cl) for you, but that's just you being lucky.

Related

Multiple Emacs Lisp config files lead to "free variable" and "function not known to be defined" warnings

I've been looking for emacs config files for a while, so that I learn how to structure my Emacs config in the most optimal way. Now i'm looking at purcell's config files which look very tidy and simple to read.
However, for every config file I've found there's always the same problem: "free variable"
and "function not known to be defined" warnings on all the included files. It is quite frustrating to see all the red underlines from flymake everytime, and it also makes me question if this really is the best way to write the config file.
Here's a file from the repository mentioned above:
;;; init-python.el --- Python editing -*- lexical-binding: t -*-
(setq auto-mode-alist
(append '(("SConstruct\\'" . python-mode)
("SConscript\\'" . python-mode))
auto-mode-alist))
;;WARNING: assignment to free variable ‘python-shell-interpreter’
(setq python-shell-interpreter "python3")
(require-package 'pip-requirements)
(when (maybe-require-package 'toml-mode)
(add-to-list 'auto-mode-alist '("poetry\\.lock\\'" . toml-mode)))
;;WARNING: reference to free variable ‘black’
(when (maybe-require-package 'reformatter)
(reformatter-define black :program "black" :args '("-")))
(provide 'init-python)
;;WARNING: the following functions are not known to be defined: require-package, maybe-require-package, reformatter-define
;;; init-python.el ends here
The python-shell-interpreter is a variable defined from the python-mode package.
The require-package and maybe-require-package are defined in a custom local file called init-elpa.el which is requires'd by the init.el file and thus they're not directly recognized by this file.
The black variable warning is the mostr "intricate": I guess it's caused by the fact that the reformatter package isn't included because maybe-require-package isn't included as well.
This gives me a headache. If I see it correctly, the root problem is the fact that the included files (init-python.el et al.) depend on stuff from the including file (init.el) without it being explicitly stated.
Is there a better way to structure an Emacs Lisp config among multiple files?
The python-shell-interpreter is a variable defined from the python-mode package.
Add (require 'python-mode) to the top of the file (or simply above the code which depends on that).
The require-package and maybe-require-package are defined in a custom local file called init-elpa.el
Add (require 'init-elpa) to the file (I'm assuming it provides the init-elpa feature).
which is require'd by the init.el file
This is fine -- require does nothing if the library in question has already been loaded. Even when there's an overarching init file loading other files, it's sensible for each file to require the things it needs (unless there are circular dependencies).
The black variable warning is the most "intricate": I guess it's caused by the fact that the reformatter package isn't included because maybe-require-package isn't included as well.
I'm guessing that reformatter-define is a macro and that the symbol black is not actually used as a variable. When only macros are required, one would typically (eval-when-compile (require 'reformatter)) but judging by the name maybe-require-package it's intended that reformatter might not be loadable at all. If that's all accurate, you can use this wrapper to cope with the false-positive:
(with-suppressed-warnings ((free-vars black))
...)
See C-hig (elisp)Compiler Errors for further information on handling byte-compilation warnings and errors.

Why is slime's "package" different from the inferior lisp?

I think I don't have a clear understanding of how slime is running lisp within Emacs.
Say I have a file with the following entries :-
(defpackage "TEST"
(:use "COMMON-LISP"))
(in-package "TEST")
*package*
Now I compile/run these three with either of say
C-c C-c
C-x C-e
and I get the output :-
#<PACKAGE "TEST">
However, if I now switch buffers to the inferior lisp buffer and type
*package*
it gives me the output as
#<PACKAGE "COMMON-LISP-USER">
What gives? Using the slime commands above clearly does something but it doesn't seem to be affecting the main REPL loop for the inferior-lisp.
Global special variables
Since global variables are using dynamic binding, one can rebind them:
CL-USER> *package*
#<The COMMON-LISP-USER package, 117/256 internal, 0/4 external>
CL-USER> (defpackage "TEST"
(:use "COMMON-LISP"))
#<The TEST package, 0/16 internal, 0/16 external>
CL-USER> (let ((*package* (find-package "TEST")))
(intern "FOO"))
So you don't need to set a global variable, you can rebind them.
So something like SLIME can rebind them and execute the code for evaluation inside the rebound variable bindings:
(let ((*package* (find-package "FOO")))
(eval (read-from-string some-string-with-code)))
Thread local global special variables
One can also create threads, such that they have their own 'thread local' global variables:
(sb-thread:make-thread (lambda (*package*)
...)
:arguments (list *package*))
Above thread function will have its own *package* variable binding.
IDE and globals
Usually one would want the IDE to use the globals in the current listener thread (each listener thread should have its own globals).
One also wants that evaluation from an editor Lisp code buffer uses the package from that buffer (typically the package defined on top or the package from the nearest IN-PACKAGE above in the code. The editor might also be able to set the package to use for the current Lisp code buffer.
Then an IDE will use something like above during evaluation: rebinding the *package* variable and/or use multiple threads with their own *package* variable binding in each thread.
IDE and multiple inferior Lisps
Typically there will be only one inferior Lisp, but it might be possible to have multiple listeners into it. Some IDEs might also support more than one inferior Lisp.
The current package in a file (or buffer actually) is determined by the first toplevel in-package form found when searching backwards from the compiled form at compilation time, e. g. when using C-c C-c to compile the toplevel form at point. I hope you can imagine the looming confusion if if were otherwise.
The current package on the REPL is set by using in-package there.
You can conveniently set the current REPL package and current directory to those of the current buffer using C-c C-~.

SLIME and Quicklisp not playing nice with each other

I'm using Emacs as my Common Lisp (SBCL, to be exact) editor, with SLIME. I set up Quicklisp as per the instructions here, and checked if it worked outside of SLIME, and everything was fine - I could grab and download code, include it, everything.
Now, I was trying to use the Compile/Load File command in Emacs for a source file with the following at the top:
(ql:quickload "priority-queue")
(defpackage :tournament
(:use :cl :priority-queue))
(in-package :tournament)
Now, once again, not in SLIME, this worked fine. However, in SLIME, I get an error of the following form:
The name "PRIORITY-QUEUE" does not designate any package.
[Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]
Plus a backtrace, of course. Am I missing something in particular? I installed slime using package-install from Emacs, and I have the following code in my .emacs file to set it up:
(setq inferior-lisp-program "/usr/local/bin/sbcl")
(require 'slime)
(slime-setup)
This is happening because of the separate times of compilation and loading.
When compiling, plain function calls (like ql:quickload) are not evaluated. When the compiler tries to process the defpackage form (which is not a plain function call, but a macro that has side-effects at compile-time), the function that loads "priority-queue" has not been called and the package is not available.
You won't see this if you load the file instead of compiling and loading, because load evaluates each form as it loads.
There are a few options available. The simplest is to wrap your call to ql:quickload in eval-when, e.g.
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload "priority-queue"))
I prefer to define a system for my projects, however small, so I would make a tournament.asd file that looks like this:
(asdf:defsystem #:tournament
:depends-on (#:priority-queue)
:serial t
:components ((:file "tournament.lisp")))
I'd put that in ~/quicklisp/local-projects/tournament/ (along with tournament.lisp) and use (ql:quickload "tournament") in the repl to get started and load it.
I use that latter setup so often that I wrote a Lisp program to do it for me called quickproject.

What Emacs Lisp function is to `require` as `autoload` is to `load`?

I am trying to program GNU Emacs 23 to issue require commands lazily, on demand, instead of up front in my .emacs file. If I wanted to delay the execution of a load command, I could use autoload. But require and load take different sorts of arguments.
Is there a predefined function that does for require the same job that autoload does for load? And if not, what tools would people recommend that I use to roll my own?
There is not difference between require and load with regards to autoload. require is just a frontend to load, which more or less comes down to:
(defun require (feature &optional filename noerror)
(unless (featurep feature)
(let ((filename (or filename (symbol-name feature))))
(load filename noerror))))
As you can see, the symbol name given to require is equal to the filename given to load. As a matter of fact, the first (require 'foo) evaluated in an Emacs session is equivalent to (load "foo").
Thus, you can just use (auto-load 'foo-function "foo") for foo-function from the library foo, that you can load with (require 'foo).
One more answer to help clarify (this was a little verbose for a comment):
autoload says "if this function isn't already defined, then load this file (if and when the function is called)."
require says "if this library isn't already loaded, then load this file (immediately)."
Note in particular that you don't need to use require to load a library; that's simply the way you ensure that you don't load it again (assuming you don't want to do that). The (provide 'FEATURE) expression in the library will be evaluated no matter how the library was loaded, which lets any future require know that it doesn't need to do anything.
It's a similar situation for autoload -- if the file has already been loaded (and therefore the function in question properly defined), then the autoload no longer has any effect.
What kind of "demand" do you have in mind for your "on demand"?
If a given command or other function needs (or soft-needs) a given library, then that function itself can use (require 'foo) or (require 'foo nil t). The library will be loaded on demand from that function.
Consider also whether you might need to load the file more than once, i.e., reload it in some situations, whether or not it has already been loaded.
For #2, for instance, my code that uses a library of Lisp macros, icicles-mac.el does not just use require, because I want to make sure that if a user gets a new version of that library (e.g., downloads a new source version and byte-compiles it) then that new version is used whenever s?he byte-compiles another library that needs it. (This is important -- when a library of macros changes, other libraries that use those macros generally need to be recompiled after loading the new macros file.) For that, instead of just (require 'icicles-mac) I use this:
(eval-when-compile
(or (condition-case nil
(load-library "icicles-mac") ; Use load-library to ensure latest .elc.
(error nil))
(require 'icicles-mac))) ; Require, so can load separately if not on `load-path'.

Emacs c-mode autoloading failed

I want to load my file named "my-c-setup.el" when the c-mode is loading. So, I'm using the function "autoload".
With my python setup, it works well :
lang.el
(autoload 'python-mode "my-python-setup" "" t)
my-python-setup.el
(require 'python)
; ...
I'm trying to do the same with the c-mode, but i does not work :
lang.el
(autoload 'c-mode "my-c-setup" "" t)
my-c-setup.el
(setq c-basic-offset 4)
; ...
When I try to open a file in c-mode (test.c for example), I have the following error :
File mode specification error: (error "Autoloading failed to define function c-mode")
Autoload is not what you're looking for. What it does is simply load some code the first time it is needed, which is a handy way to extend Emacs' functionality while still keeping the start-up time low.
To solve your problem, we gotta think about what you really want to do: do you simply want some of your code to be loaded at some point, or do you want buffer-local customizations for ever buffer that is in c-mode?
If you simply want Emacs to load your code at start-up, either put your code directly into your .emacs file or use load-file or require instead of autoload:
load-file simply takes a file name, loads the lisp code in that file and evaluates it. So if your code is in a file named "/path/to/my-c-setup.el", you could put the following line in your .emacs, and the code will be loaded on every start-up:
(load-file "/path/to/my-c-setup.el")
Perhaps you don't want to give the absolute path name for every file you load. In that case, you could use the function load-library instead which is similar to load-file but tries to find the given filename in any of the directories stored in the variable load-path:
(add-to-list 'load-path "/path/to")
(load-library "my-c-setup.el")
The advantage is that you have to do the add-to-list part only once, and all subsequent calls to load-library will be able to find code in that directory.
An alternative way is the provide/require mechanism: you can make your .el-file "provide" some feature by putting a (provide 'feature) call in it, e.g.
(provide 'my-c-mode-customizations)
Then put an according (require 'feature) in your .emacs file, and your code will be loaded as well:
(require 'my-c-mode-customizations)
However, if you want your code only be loaded when c-mode is activated on a buffer, the way to achieve that is through Emacs' Hook mechanism:
A hook is a variable where you can
store a function or functions to be
called on a particular occasion by an
existing program.
Most major modes provide a customizable hook variable to which you can add functions that will be called whenever the major mode is invoked. For instance, c-mode provides c-mode-hook. In order for your own customizations to be called whenever c-mode is turned on for a buffer, put them in a function, say, my-c-mode-customizations and add the following line to your .emacs file:
(add-hook 'c-mode-hook 'my-c-mode-customizations)
Of course, you still need autoload for Emacs to actually find the definition of that function.
Lisp's autoload does not call a function when a file is loaded but tells lisp that the function is available and that the given file provides it. Whenever someone calls the (not yet defined) function, the file is loaded.
I think that c-mode is already defined and thus fails to re-register.
Autoload doesn't do what you think it does.
http://www.gnu.org/software/emacs/elisp/html_node/Autoload.html
What you probably want are mode-hooks or eval-after-load.
See eval-after-load vs. mode hook for the difference between the two.