tpapp / julia-repl

Run an inferior Julia REPL in a terminal inside Emacs
Other
169 stars 35 forks source link

"Warning (emacs): could not capture basedir for Julia executable nil" and "Lisp error: (wrong-type-argument stringp nil)" #140

Closed YueRen closed 1 year ago

YueRen commented 1 year ago
  1. Emacs version (installed via apt on Ubuntu 22.04.2):

    GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.30, cairo version 1.16.0) of 2022-01-24, modified by Debian
  2. the Julia version (VERSION): v"1.8.5"

  3. julia-repl version: freshly installed from melpa, should be latest commit 57a15d

My init.el reads (path is what I get when running which julia in my terminal):

(add-to-list 'load-path "/home/ren/julia-1.8.5/bin/julia")
(use-package julia-repl)
(add-hook 'julia-mode-hook 'julia-repl-mode) ;; always use minor mode

When running M-x julia-repl, I get an empty *julia* buffer and the following warning:

Warning (emacs): could not capture basedir for Julia executable nil

Activating M-x toggle-debug-on-error yields:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  #<subr make-process>(:name "julia" :buffer #<buffer *julia*> :command ("/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil))
  apply(#<subr make-process> (:name "julia" :buffer #<buffer *julia*> :command ("/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil)))
  make-process--with-editor-process-filter(#<subr make-process> :name "julia" :buffer #<buffer *julia*> :command ("/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil))
  apply(make-process--with-editor-process-filter #<subr make-process> (:name "julia" :buffer #<buffer *julia*> :command ("/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil)))
  make-process(:name "julia" :buffer #<buffer *julia*> :command ("/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil))
  apply(make-process (:name "julia" :buffer #<buffer *julia*> :command ("/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil)))
  start-process("julia" #<buffer *julia*> "/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil)
  apply(start-process "julia" #<buffer *julia*> "/bin/sh" "-c" "stty -nl echo rows 17 columns 141 sane 2>/dev/null..." ".." nil nil)
  term-exec-1("julia" #<buffer *julia*> nil nil)
  term-exec(#<buffer *julia*> "julia" nil nil nil)
  make-term("julia" nil nil)
  apply(make-term "julia" nil nil nil)
  (let ((inferior-buffer (apply #'make-term name executable-path nil switches))) (save-current-buffer (set-buffer inferior-buffer) (mapc #'(lambda (k) (define-key term-raw-map k (global-key-binding k))) julia-repl-captures) (term-char-mode) (if julia-repl-set-term-escape (progn (term-set-escape-char 24))) (set (make-local-variable 'term-prompt-regexp) "^(julia|shell|help\\?|(\\d+\\|debug ))>") (if (version< emacs-version "27") (progn (set (make-local-variable 'term-suppress-hard-newline) t))) (set (make-local-variable 'term-scroll-show-maximum-output) t) (set (make-local-variable 'term-scroll-to-bottom-on-output) t)) inferior-buffer)
  (progn (let ((inferior-buffer (apply #'make-term name executable-path nil switches))) (save-current-buffer (set-buffer inferior-buffer) (mapc #'(lambda (k) (define-key term-raw-map k (global-key-binding k))) julia-repl-captures) (term-char-mode) (if julia-repl-set-term-escape (progn (term-set-escape-char 24))) (set (make-local-variable 'term-prompt-regexp) "^(julia|shell|help\\?|(\\d+\\|debug ))>") (if (version< emacs-version "27") (progn (set (make-local-variable 'term-suppress-hard-newline) t))) (set (make-local-variable 'term-scroll-show-maximum-output) t) (set (make-local-variable 'term-scroll-to-bottom-on-output) t)) inferior-buffer))
  (closure (cl-struct-julia-repl--buffer-ansi-term-tags t) (_terminal-backend name executable-path switches) (progn (let ((inferior-buffer (apply #'make-term name executable-path nil switches))) (save-current-buffer (set-buffer inferior-buffer) (mapc #'(lambda ... ...) julia-repl-captures) (term-char-mode) (if julia-repl-set-term-escape (progn (term-set-escape-char 24))) (set (make-local-variable 'term-prompt-regexp) "^(julia|shell|help\\?|(\\d+\\|debug ))>") (if (version< emacs-version "27") (progn (set ... t))) (set (make-local-variable 'term-scroll-show-maximum-output) t) (set (make-local-variable 'term-scroll-to-bottom-on-output) t)) inferior-buffer)))(#s(julia-repl--buffer-ansi-term) "julia" nil nil)
  apply((closure (cl-struct-julia-repl--buffer-ansi-term-tags t) (_terminal-backend name executable-path switches) (progn (let ((inferior-buffer (apply #'make-term name executable-path nil switches))) (save-current-buffer (set-buffer inferior-buffer) (mapc #'(lambda ... ...) julia-repl-captures) (term-char-mode) (if julia-repl-set-term-escape (progn (term-set-escape-char 24))) (set (make-local-variable 'term-prompt-regexp) "^(julia|shell|help\\?|(\\d+\\|debug ))>") (if (version< emacs-version "27") (progn (set ... t))) (set (make-local-variable 'term-scroll-show-maximum-output) t) (set (make-local-variable 'term-scroll-to-bottom-on-output) t)) inferior-buffer))) #s(julia-repl--buffer-ansi-term) ("julia" nil nil))
  julia-repl--make-buffer(#s(julia-repl--buffer-ansi-term) "julia" nil nil)
  (let* ((executable-path (julia-repl--executable-path executable-record)) (basedir (plist-get (cdr (cdr executable-record)) :basedir)) (inferior-buffer (julia-repl--make-buffer terminal-backend name executable-path (if switches (progn (split-string switches)))))) (if julia-repl-compilation-mode (progn (julia-repl--setup-compilation-mode inferior-buffer basedir))) (julia-repl--run-hooks inferior-buffer) (save-current-buffer (set-buffer inferior-buffer) (set (make-local-variable 'julia-repl--inferior-buffer-suffix) suffix)) inferior-buffer)
  (let ((executable-record (julia-repl--executable-record executable-key)) (switches julia-repl-switches)) (julia-repl--complete-executable-record! executable-record) (let* ((executable-path (julia-repl--executable-path executable-record)) (basedir (plist-get (cdr (cdr executable-record)) :basedir)) (inferior-buffer (julia-repl--make-buffer terminal-backend name executable-path (if switches (progn (split-string switches)))))) (if julia-repl-compilation-mode (progn (julia-repl--setup-compilation-mode inferior-buffer basedir))) (julia-repl--run-hooks inferior-buffer) (save-current-buffer (set-buffer inferior-buffer) (set (make-local-variable 'julia-repl--inferior-buffer-suffix) suffix)) inferior-buffer))
  (if live-buffer live-buffer (let ((executable-record (julia-repl--executable-record executable-key)) (switches julia-repl-switches)) (julia-repl--complete-executable-record! executable-record) (let* ((executable-path (julia-repl--executable-path executable-record)) (basedir (plist-get (cdr (cdr executable-record)) :basedir)) (inferior-buffer (julia-repl--make-buffer terminal-backend name executable-path (if switches (progn ...))))) (if julia-repl-compilation-mode (progn (julia-repl--setup-compilation-mode inferior-buffer basedir))) (julia-repl--run-hooks inferior-buffer) (save-current-buffer (set-buffer inferior-buffer) (set (make-local-variable 'julia-repl--inferior-buffer-suffix) suffix)) inferior-buffer)))
  (let* ((name (julia-repl--inferior-buffer-name executable-key suffix)) (live-buffer (julia-repl--locate-live-buffer terminal-backend name))) (if live-buffer live-buffer (let ((executable-record (julia-repl--executable-record executable-key)) (switches julia-repl-switches)) (julia-repl--complete-executable-record! executable-record) (let* ((executable-path (julia-repl--executable-path executable-record)) (basedir (plist-get (cdr ...) :basedir)) (inferior-buffer (julia-repl--make-buffer terminal-backend name executable-path (if switches ...)))) (if julia-repl-compilation-mode (progn (julia-repl--setup-compilation-mode inferior-buffer basedir))) (julia-repl--run-hooks inferior-buffer) (save-current-buffer (set-buffer inferior-buffer) (set (make-local-variable 'julia-repl--inferior-buffer-suffix) suffix)) inferior-buffer))))
  (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '(:executable-key :suffix :terminal-backend :allow-other-keys)) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq ... --cl-rest--))) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:executable-key :s..." (car --cl-keys--)))))) (let* ((name (julia-repl--inferior-buffer-name executable-key suffix)) (live-buffer (julia-repl--locate-live-buffer terminal-backend name))) (if live-buffer live-buffer (let ((executable-record (julia-repl--executable-record executable-key)) (switches julia-repl-switches)) (julia-repl--complete-executable-record! executable-record) (let* ((executable-path (julia-repl--executable-path executable-record)) (basedir (plist-get ... :basedir)) (inferior-buffer (julia-repl--make-buffer terminal-backend name executable-path ...))) (if julia-repl-compilation-mode (progn (julia-repl--setup-compilation-mode inferior-buffer basedir))) (julia-repl--run-hooks inferior-buffer) (save-current-buffer (set-buffer inferior-buffer) (set (make-local-variable ...) suffix)) inferior-buffer)))))
  (let* ((executable-key (car (cdr (or (plist-member --cl-rest-- ':executable-key) (list nil (julia-repl--get-executable-key)))))) (suffix (car (cdr (or (plist-member --cl-rest-- ':suffix) (list nil julia-repl-inferior-buffer-name-suffix))))) (terminal-backend (car (cdr (or (plist-member --cl-rest-- ':terminal-backend) (list nil julia-repl--terminal-backend)))))) (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '...) (setq --cl-keys-- (cdr ...))) ((car (cdr ...)) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:executable-key :s..." (car --cl-keys--)))))) (let* ((name (julia-repl--inferior-buffer-name executable-key suffix)) (live-buffer (julia-repl--locate-live-buffer terminal-backend name))) (if live-buffer live-buffer (let ((executable-record (julia-repl--executable-record executable-key)) (switches julia-repl-switches)) (julia-repl--complete-executable-record! executable-record) (let* ((executable-path ...) (basedir ...) (inferior-buffer ...)) (if julia-repl-compilation-mode (progn ...)) (julia-repl--run-hooks inferior-buffer) (save-current-buffer (set-buffer inferior-buffer) (set ... suffix)) inferior-buffer))))))
  julia-repl-inferior-buffer()
  (let ((script-buffer (current-buffer)) (inferior-buffer (julia-repl-inferior-buffer))) (save-current-buffer (set-buffer inferior-buffer) (setq julia-repl--script-buffer script-buffer)) (pop-to-buffer inferior-buffer))
  julia-repl()
  funcall-interactively(julia-repl)
  call-interactively(julia-repl record nil)
  command-execute(julia-repl record)
  execute-extended-command(nil "julia-repl" "juli")
  funcall-interactively(execute-extended-command nil "julia-repl" "juli")
  call-interactively(execute-extended-command nil nil)
  command-execute(execute-extended-command)
YueRen commented 1 year ago

Some more info: In Ubuntu 22.04 julia-repl works just fine if I use it in an emacs started from the terminal, i.e., by running emacs or emacs & from the terminal.

I only get the error above if I start emacs using Windows key + typing emacs in the search bar + clicking the emacs icon that pops up.

jlV1000 commented 1 year ago

Hello

Same problem on 22.04.1-Ubuntu and elpa packages installed julia-repl works with emacs-nox package (terminal version of emacs) but get "Warning (emacs): could not capture basedir for Julia executable nil" with emacs-gtk package (GUI emacs) and with the same init.el :

let ((default-directory "~/julia/julia-1.8.5/")) (normal-top-level-add-subdirs-to-load-path)) (require 'julia-mode) (require 'julia-repl) (add-hook 'julia-mode-hook 'julia-repl-mode) ;; always use minor mode (julia-repl-set-terminal-backend 'vterm)

So it seems that the problem is an incompatibility with emacs-gtk

YueRen commented 1 year ago

@jlV1000 Regarding incompatibilities with emacs-gtk being the potential cause of the problem: Starting emacs from the terminal via gtk-launch emacs or emacs-gtk gives me an emacs in which I can run julia-repl. I only have a problem when starting it via the menu that pops up in Ubuntu when pressing the Windows key.

tpapp commented 1 year ago

I only have a problem when starting it via the menu that pops up in Ubuntu when pressing the Windows key.

Are you sure they are running the same executable? You could have an older version of Emacs somewhere that shows up in the menu. What's the M-x emacs-version in the version where you get the problem?

YueRen commented 1 year ago

Good question. I get the following whether I start emacs using the Ubuntu Windows key menu (in which julia-repl does not work) or via typing emacs in the terminal (in which julia-repl does work):

Not sure what else to check to see the difference.

tpapp commented 1 year ago

What does which emacs say in the terminal? (this gives you the executable path)

Also namei `which-emacs` or something similar will give you the actual (non-symlink) path. Can you look it up with dpkg -S to see if it comes from a package?

YueRen commented 1 year ago

I hope I understood your request correctly. This is what I get when I type namei 'which emacs' in my terminal:

ren@thinkpad:~$ namei `which emacs`
f: /usr/bin/emacs
 d /
 d usr
 d bin
 l emacs -> /etc/alternatives/emacs
   d /
   d etc
   d alternatives
   l emacs -> /usr/bin/emacs-gtk
     d /
     d usr
     d bin
     - emacs-gtk

(For context: starting emacs from the terminal via emacs-gtk does give me an emacs in which julia-repl works. Not sure which emacs is started via the Ubuntu menu)

tpapp commented 1 year ago

So let's figure that out.

For each emacs (the one that works, and the one that does not),

  1. start the emacs process. make sure no other emacs is running
  2. in the terminal, ps -ef | grep -i emacs, the last column of the relevant process gives you the emacs path
  3. chase it down with namei,
  4. run dpkg -S <path> on the result to see which package it is coming from, if applicable.
YueRen commented 1 year ago

Here's the output for the emacs that does not work (started using Ubuntu menu):

ren@thinkpad:~$ ps -ef | grep -i emacs
ren        39895    4863 48 13:13 ?        00:00:04 /usr/bin/emacs
ren        39982   36044  0 13:13 pts/2    00:00:00 grep -i emacs
ren@thinkpad:~$ namei /usr/bin/emacs
f: /usr/bin/emacs
 d /
 d usr
 d bin
 l emacs -> /etc/alternatives/emacs
   d /
   d etc
   d alternatives
   l emacs -> /usr/bin/emacs-gtk
     d /
     d usr
     d bin
     - emacs-gtk
ren@thinkpad:~$ dpkg -S /usr/bin/emacs
dpkg-query: no path found matching pattern /usr/bin/emacs

Here's the output for the emacs that works (started from the terminal):

ren@thinkpad:~$ ps -ef | grep -i emacs
ren        40115   40106 50 13:15 pts/0    00:00:04 emacs
ren        40129   36044  0 13:15 pts/2    00:00:00 grep -i emacs
ren@thinkpad:~$ namei emacs
f: emacs
   emacs - No such file or directory
ren@thinkpad:~$ which emacs
/usr/bin/emacs

Both seem to run the same /usr/bin/emacs (which dpkg -S does not recognize), the only difference is in the TTY column of ps -ef.

tpapp commented 1 year ago

You need to query with the full, final path, eg

dpkg -S /usr/bin/emacs-gtk

It would be interesting to see if removing this package leads to any changes, eg makes one of the options not start. Then the other one is running something else.

That said, it seems emacs just runs /usr/bin/emacs, which leads to /usr/bin/emacs-gtk. So I am puzzled about what is going on.

jlV1000 commented 1 year ago

Exactly the same as YueRen. Does not work with icon on X11, works with launch from terminal. Same output for ps -ef | grep -i emacs and namei,

dpkg -S /usr/bin/emacs-gtk emacs-gtk: /usr/bin/emacs-gtk

Note that whatever the method to launch emacs, emacs prints in its first screnn This is GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.30, cairo version 1.16.0)

YueRen commented 1 year ago

You need to query with the full, final path, e.g. dpkg -S /usr/bin/emacs-gtk

Ah, my bad.

ren@thinkpad:~$ dpkg -S /usr/bin/emacs-gtk
emacs-gtk: /usr/bin/emacs-gtk

That said, it seems emacs just runs /usr/bin/emacs, which leads to /usr/bin/emacs-gtk. So I am puzzled about what is going on.

It does seem more like an Ubuntu issue rather than an emacs issue. My first instinct was also asking on askUbuntu but nobody was able to help me there.

tpapp commented 1 year ago

Even if it is the same executable, the environment could be different. Can you paste the value of the following variables from within Emacs here (eg with C-h v):

  1. julia-repl-executable-records
  2. exec-path

Please do it for both versions of starting up Emacs.

jlV1000 commented 1 year ago

Exact, not the same environment. It seems that the init.el (~/emacs.d/init.el) is not read in the not working version. indeed, the path to julia folder does not appear. The init.el begin with (let ((default-directory "~/julia/julia-1.8.5/")) (normal-top-level-add-subdirs-to-load-path))

***** Working version: julia-repl-executable-records is a variable defined in ‘julia-repl.el’. ((default "julia" :basedir "/home/thomas/julia/julia-1.8.5/share/julia/base"))

exec-path ...("/home/thomas/mambaforge/bin" "/home/thomas/mambaforge/condabin" "/usr/local/sbin" "/usr/local/bin" "/usr/sbin" "/usr/bin" "/sbin" "/bin" "/usr/games" "/usr/local/games" "/snap/bin" "/snap/bin" "/home/thomas/julia/julia-1.8.5/bin" "/usr/lib/emacs/27.1/x86_64-linux-gnu")

***** Not working version: julia-repl-executable-records is a variable defined in ‘julia-repl.el’. Its value is ((default "julia")) exec-path ("/usr/local/sbin" "/usr/local/bin" "/usr/sbin" "/usr/bin" "/sbin" "/bin" "/usr/games" "/usr/local/games" "/snap/bin" "/snap/bin" "/usr/lib/emacs/27.1/x86_64-linux-gnu")

tpapp commented 1 year ago

This may be about paths then. You can set julia-repl-executable-records explicitly in init.el, eg

(setq julia-executable-records '((v1.8 "/absolute/path/to/wherever/julia_is")))

My guess is that you are setting PATH in the shell config files, but not exporting it. So Emacs started from the menu does not know about it.

jlV1000 commented 1 year ago

Thank you for your work and help, in any case julia-repl works launching emacs from terminal. I have in .bashrc export PATH="$PATH:/home/thomas/julia/julia-1.8.5/bin" and echo $PATH return /home/thomas/mambaforge/bin:/home/thomas/mambaforge/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/home/thomas/julia/julia-1.8.5/bin

YueRen commented 1 year ago

This may be about paths then. You can set julia-repl-executable-records explicitly in init.el, eg

(setq julia-executable-records '((v1.8 "/absolute/path/to/wherever/julia_is")))

My guess is that you are setting PATH in the shell config files, but not exporting it. So Emacs started from the menu does not know about it.

That was exactly it! I couldn't figure out how to fix the issue by changing julia-executable-records, but changing exec-path by adding the following line to my init file fixed it for me:

(setq exec-path (append exec-path '("/home/ren/julia-1.8.5/bin")))
tpapp commented 1 year ago

I am glad that this is resolved, closing the issue.