Function sent to REPL with ,d is added to wrong package
MaxGyver83 opened this issue · 15 comments
I have this minimal Common Lisp file:
(defpackage :my-package (:use :cl))
(in-package :my-package)
(defun my-function () (write-line "hello"))
(my-function)
When I connect to the swank server with ,c
and then evaluate one line after another with ,d
, the new function my-function
is added to CL-USER
instead of MY-PACKAGE
. When I copy the defun
line and paste it to the REPL, it's added to MY-PACKAGE
.
Any idea what could be wrong?
SBCL 2.3.7 Port: 4005 Pid: 430116
; SWANK 2.26
CL-USER> (defpackage :my-package (:use :cl))
#<PACKAGE "MY-PACKAGE">
CL-USER> (in-package :my-package)
#<PACKAGE "MY-PACKAGE">
MY-PACKAGE> (defun my-function () (write-line "hello"))
MY-FUNCTION
MY-PACKAGE> (describe #'MY-FUNCTION)
The function MY-PACKAGE::MY-FUNCTION is undefined.
[Condition of type UNDEFINED-FUNCTION]
; Evaluation aborted on NIL
MY-PACKAGE> ; Quit to level 1
MY-PACKAGE> ; Evaluation aborted on #<UNDEFINED-FUNCTION MY-FUNCTION {10023DF2B3}>
MY-PACKAGE> (describe #'CL-USER::MY-FUNCTION)
#<FUNCTION COMMON-LISP-USER::MY-FUNCTION>
[compiled function]
Lambda-list: ()
Derived type: (FUNCTION NIL
(VALUES (SIMPLE-ARRAY CHARACTER (5)) &OPTIONAL))
Source form:
(LAMBDA () (BLOCK COMMON-LISP-USER::MY-FUNCTION (WRITE-LINE "hello")))
; No value
copy-pasting here:
MY-PACKAGE> (defun my-function () (write-line "hello"))
MY-FUNCTION
MY-PACKAGE> (describe #'MY-FUNCTION)
#<FUNCTION MY-FUNCTION>
[compiled function]
Lambda-list: ()
Derived type: (FUNCTION NIL
(VALUES (SIMPLE-ARRAY CHARACTER (5)) &OPTIONAL))
Source form:
(LAMBDA () (BLOCK MY-FUNCTION (WRITE-LINE "hello")))
; No value
More information
:echo g:slimv_lisp
sbcl
:echo g:slimv_impl
sbcl
$ pgrep -fa sbcl
131524 sbcl --load /home/max/.vim/pack/plugins/start/slimv/slime/start-swank.lisp
$ sbcl --version
SBCL 2.3.7
When I comment out this part in my ~/.sbclrc
, it works again:
(if (member "--no-linedit" sb-ext:*posix-argv* :test 'equal)
(setf sb-ext:*posix-argv*
(remove "--no-linedit" sb-ext:*posix-argv* :test 'equal))
(when (interactive-stream-p *terminal-io*)
(require :sb-aclrepl)
(require :linedit)
(funcall (intern "INSTALL-REPL" :linedit)
:wrap-current t
:eof-quits t
:history "~/.sbcl_history")))
When I keep these lines in and set let g:slimv_lisp = 'sbcl --noinform --no-linedit'
in my .vimrc
, swank doesn't start at all (after typing ,c
):
SWANK server is not running. Press ENTER to continue.
Same error when I set g:slimv_swank_cmd
like this:
let g:slimv_swank_cmd = '!tmux new-window -d -n REPL-SBCL "sbcl --noinform --no-linedit --load ~/.vim/pack/plugins/start/slimv/slime/start-swank.lisp"'
On the Linedit homepage, they recommend to add this line to .emacs
:
(setq inferior-lisp-program "sbcl --noinform --no-linedit")
This is why I tried adding --noinform --no-linedit
to g:slimv_lisp
and g:slimv_swank_cmd
.
This in my .vimrc
works:
let g:slimv_swank_cmd = '!tmux new-window -d -n REPL-SBCL "sbcl --noinform --no-userinit --load ~/.vim/pack/plugins/start/slimv/slime/start-swank.lisp"'
let g:slimv_lisp = 'sbcl --noinform --no-userinit'
Update: let g:slimv_lisp = 'sbcl --noinform --no-userinit'
isn't necessary.
Thank you for the feedback and sorry for the delay. I tried to reproduce the problem but on my system my-function
was added to my-package
even if evaluated line-by-line.
Please enable the swank debug log info, so that we can see what is the communication between slimv and the swank server. The package is part of the communication, e.g. this is the function definition evaluation on my system:
(:emacs-rex (swank-repl:listener-eval "(defun my-function () (write-line \"hello\"))
") ":my-package" :repl-thread 6)
You can enable debug log info by adding this line to your .vimrc:
let g:swank_log = 1
After that a swank.log file will be created in your working directory. Please repeat the test and paste the part of the log where you evaluate the buffer line-by-line (or just simply send the whole swank.log file to me).
Thank you for the assistance.
Thanks for your support!
It looks like I can't reproduce this issue. I have tried different values for g:slimv_lisp
and g:slimv_swank_cmd
and now it works for every combination I have tried.
I suspect that this issue was caused by a broken (quicklisp?) cache, maybe after installing roswell next to Arch's sbcl
!? I was wondering that sbcl showed a long list of quicklisp command after every single start. Then I deleted the cache (~/.cache/common-lisp/sbcl-2.3.7-linux-x64/
) and the quicklisp issue was gone. Maybe that's the reason I don't need this configuration anymore:
let g:slimv_swank_cmd = '!tmux new-window -d -n REPL-SBCL "sbcl --noinform --no-userinit --load ~/.vim/pack/plugins/start/slimv/slime/start-swank.lisp"'
Now the problem is back. This time, I'm trying to connect to StumpWM's swank server. (Also see Hacking StumpWM with vim · stumpwm/stumpwm · Discussion #1139).
I have tried to debug this. The problem seems to be that initially after opening ~/.config/stumpwm/config
, iskeyword
doesn't contain a hyphen:
echo &iskeyword
@,48-57,_,192-255,&
When I send a form with ,d
, the function SlimvFindPackage()
sets s:swank_package
and s:swank_package_form
wrongly:
s:swank_package = '(in-package'
s:swank_package_form = '(in (in-package)'
The reason is that the second silent normal! w moves the cursor in (in-package :stumpwm)
from i
to -
.
Only after inserting a blank and pressing Escape, iskeyword
is extended:
echo &iskeyword
@,48-57,_,192-255,&,+,-,*,/,%,<,=,>,:,$,?,!,@-@,94,~,#,|,&,.,{,},[,]
Now a w
moves the cursor from i
to :
.
Any idea how to fix?
I think replacing w
by W
would help but the cword
expansion above would still be wrong. Temporarily setting the needed value for iskeyword
might fix this.
call s:SetKeyword()
after line ftplugin/slimv.vim +1330 seems to fix this issue for me.
Before:
[---Sent---] 1341.152077888
(:emacs-rex (swank-repl:create-repl nil) "(in-package" t 3)
[-Received-] 1341.157278291
(:return (:ok ("SWANK-FUZZY" "SWANK-FANCY-INSPECTOR" "SWANK-PACKAGE-FU" "SWANK-ASDF" "SWANK-ARGLISTS" "ASDF" "asdf" "UIOP" "uiop" "SWANK-PRESENTATIONS" "SWANK-REPL" "SWANK-C-P-C" "SWANK-UTIL" "SB-CLTL2" "SB-POSIX" "SB-INTROSPECT" "SB-BSD-SOCKETS")) 2)
[Actionlist] 1341.157453737
2: finished :swank-require
3: pending :create-repl
params: ['"SWANK-FUZZY"', '"SWANK-FANCY-INSPECTOR"', '"SWANK-PACKAGE-FU"', '"SWANK-ASDF"', '"SWANK-ARGLISTS"', '"ASDF"', '"asdf"', '"UIOP"', '"uiop"', '"SWANK-PRESENTATIONS"', '"SWANK-REPL"', '"SWANK-C-P-C"', '"SWANK-UTIL"', '"SB-CLTL2"', '"SB-POSIX"', '"SB-INTROSPECT"', '"SB-BSD-SOCKETS"']
[-Received-] 1341.162787254
(:return (:ok ("COMMON-LISP-USER" "CL-USER")) 3)
After:
[---Sent---] 336.379557668
(:emacs-rex (swank-repl:create-repl nil) ":stumpwm" t 3)
[-Received-] 336.380848173
(:return (:ok ("COMMON-LISP-USER" "CL-USER")) 3)
[Actionlist] 336.380969588
3: finished :create-repl
params: ['"COMMON-LISP-USER"', '"CL-USER"']
Somehow the sent form is accepted and applied in the stumpwm package but on the other hand, swank returns "COMMON-LISP-USER"/"CL-USER" and shows "CL-USER" in the REPL prompt:
1 SBCL 2.3.7 Port: 4005 Pid: 775
2 ; SWANK 2.28
3 CL-USER> (set-prefix-key (kbd "s-space"))
4 NIL
5 CL-USER>
Could you please check where is option iskeyword
set in your system? Just open a .lisp file then enter this command:
:verbose set iskeyword?
For .lisp files it should contain some special characters that do not seem to be included on your system. I think the default vim lisp ftplugin contains these. This is the output on my system:
iskeyword=@,48-57,_,192-255,+,-,*,/,%,<,=,>,:,$,?,!,@-@,94
Last set from /usr/share/vim/vim82/ftplugin/lisp.vim line 20
vim version 9.0.1882
.
Just vim
or vim -u NORC
:
:verbose set iskeyword?
iskeyword=@,48-57,_,192-255,&
Last set from /usr/share/vim/vimfiles/after/syntax/lisp.vim line 5
When I open a lisp file with vim -u DEFAULTS
or vim --noplugin
:
:verbose set iskeyword?
iskeyword=@,48-57,_,192-255,+,-,*,/,%,<,=,>,:,$,?,!,@-@,94,&
Last set from /usr/share/vim/vimfiles/after/syntax/lisp.vim line 5
/usr/share/vim/vimfiles/after/syntax/lisp.vim
line 5 just adds an ampersand:
set iskeyword+=&
The only syntax/lisp.vim
that I can find in the vim repository looks different:
https://github.com/vim/vim/blob/master/runtime/syntax/lisp.vim
The difference between the two iskeyword
outputs above seems to be in this line:
setl iskeyword+=+,-,*,/,%,<,=,>,:,$,?,!,@-@,94
(Same in my local /usr/share/vim/vim90/ftplugin/lisp.vim
.)
When I comment out set iskeyword+=&
in /usr/share/vim/vimfiles/after/syntax/lisp.vim
and execute :verbose set iskeyword?
again, the output is:
iskeyword=@,48-57,_,192-255
Last set from ~/.vimrc line 1
And line 1 in my ~/.vimrc
is set nocompatible
.
When I comment out this line, I get:
iskeyword=@,48-57,_,192-255
Last set from /usr/share/vim/vimfiles/archlinux.vim line 13
When I comment out this line in /usr/share/vim/vimfiles/archlinux.vim
, I get only:
iskeyword=@,48-57,_,192-255
Finally I got it:
Only when I use vim -u DEFAULTS
or vim --noplugin
, line 20 of /usr/share/vim/vim90/ftplugin/lisp.vim
extends iskeyword
. Otherwise the file is skipped because my ~/.vim/ftplugin/lisp.vim
(in which I set slimv options, for example) replaces the system's ftplugin
.
The correct way is to move my ~/.vim/ftplugin/lisp.vim
to ~/.vim/after/ftplugin/lisp.vim
.
My fault! 🙃 Sorry for the trouble and thanks for your support. Using verbose set iskeyword?
led me to my misconfiguration!
One more question:
Should the REPL prompt show the current package?
When the REPL is created like this:
[---Sent---] 6439.276644843
(:emacs-rex (swank-repl:create-repl nil) "stumpwm" t 3)
I get a CL-USER>
prompt. Even when I execute in-package
, the prompt still shows CL-USER>
:
SBCL 2.3.7 Port: 4005 Pid: 815
; SWANK 2.28
CL-USER> (in-package :stumpwm)
#<PACKAGE "STUMPWM">
CL-USER> *package*
#<PACKAGE "STUMPWM">
CL-USER>
Every swank server message contains a package where the specific message is to be executed. If for an in-package
message the current package differs from the one sent in the message, then the swank server responds with a :new-package
, slimv catches it and changes the prompt. I assume that your swank server did not respond with a :new-package
. I'm not sure why, but you can check it in the swank.log
file.
When you eval an :(in-package :xxx)
from a .lisp file by pressing ,d
then the swank server again may not respond with :new-package
, because there slimv checks the package definitions in the file and sets the current package for the swank server for every evaluation message. Therefore the swank server thinks that you are already in that package and does not respond with a :new-package
.
This is a sample when I eval in-package
via ,d
:
(:emacs-rex (swank-repl:listener-eval "(in-package :my-package)") ":my-package" :repl-thread 5)
This is a sample when I enter the same in the REPL buffer, note that here `COMMON-LISP-USER' was passed as current package:
(:emacs-rex (swank-repl:listener-eval "(in-package :my-package)") "COMMON-LISP-USER" :repl-thread 7)
...
(:new-package "MY-PACKAGE" "MY-PACKAGE")
Thanks for the explanation! I can confirm that swank never answers with :new-package
. It always looks like in your first example: (in-package :stumpwm)
is always executed in the stumpwm
package, so the two packages always match.
When I set let g:slimv_package = 0
, I can update the prompt by sending an in-package
expression.
What is the intended behavior with let g:slimv_package = 1
? Would it make sense to treat in-package
expressions as a special case and not to reset the package after the expression has been evaluated? Or maybe even never to reset the package!?
g:slimv_package
is just for backward compatilibity with very old versions of slimv that did not handle packages at all. There is not much use of it right now, I think. Anyway, if it is set to 0, then slimv does not handle packages at all.
in-package
: the package variable is reset because you can have multiple buffers open, some of have no packages at all. If we just simply keep the current package, then the other buffer with no package would be evaluated with an incorrect package. Or even in the same buffer, the first few lines may not contain any package information. So resetting the package after each evaluation seemed a reasonable approach.