greghendershott / racket-mode

Emacs major and minor modes for Racket: edit, REPL, check-syntax, debug, profile, packages, and more.
https://www.racket-mode.com/
GNU General Public License v3.0
683 stars 93 forks source link

Cannot start racket-repl: works only in racket-mode #713

Closed kurniawano closed 5 months ago

kurniawano commented 5 months ago

Hi, I'm new to racket and trying out racket-mode. I'm using Emacs 29.3.

Steps to reproduce: I installed racket-mode using package-install and set the following in my init.el.

(add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))
(setq racket-racket-program "/Applications/Racket v8.13/bin/racket")
(setq racket-raco-program "/Applications/Racket v8.13/bin/racket")

I then open any .rkt file.

I can start racket-mode since I see the work "Racket" at my Emacs bar. However, every time I run M-x racket-repl it shows the following error.

racket-repl works only in racket-mode or racket-hash-lang-mode edit buffers

I'm not sure what's the issue.

Below is the bug-report detail:

Package

metadata
(#s(package-desc racket-mode
                 (20240612 1256)
                 "Racket editing, REPL, and more"
                 ((emacs
                   (25 1)))
                 nil nil "/Users/oka_kurniawan/.emacs.d/elpa/racket-mode-20240612.1256"
                 ((:url . "https://www.racket-mode.com/")
                  (:maintainer "Greg Hendershott")
                  (:maintainers
                   ("Greg Hendershott"))
                  (:authors
                   ("Greg Hendershott" . "racket-mode-author@greghendershott.com"))
                  (:commit . "4cdbc1deb30c1625fadde762e55eb78c3acede53"))
                 nil))
package-archives
(("gnu" . "https://elpa.gnu.org/packages/")
 ("nongnu" . "https://elpa.nongnu.org/nongnu/")
 ("tromey" . "http://tromey.com/elpa/")
 ("melpa" . "https://melpa.org/packages/"))
racket--el-source-dir
"/Users/oka_kurniawan/.emacs.d/elpa/racket-mode-20240612.1256/"
racket--rkt-source-dir
"/Users/oka_kurniawan/.emacs.d/elpa/racket-mode-20240612.1256/racket/"

System values

emacs-version
"29.3"
major-mode
help-mode
system-type
darwin
display-graphic-p
t

Buffer values

after-change-functions
nil
before-change-functions
nil
completion-at-point-functions
(tags-completion-at-point-function)
eldoc-documentation-function
eldoc-documentation-default
font-lock-defaults
nil
pre-command-hook
(tooltip-hide)
post-command-hook
(global-font-lock-mode-check-buffers global-eldoc-mode-check-buffers global-display-line-numbers-mode-check-buffers ido-cr+-schedule-dynamic-collection-update global-hl-line-highlight mode-local-post-major-mode-change)
post-self-insert-hook
(electric-indent-post-self-insert-function blink-paren-post-self-insert-function)
xref-backend-functions
(etags--xref-backend)

Racket Mode values

racket--cmd-open-p
t
racket-after-run-hook
nil
racket-back-end-configurations
((:directory "/" :racket-program nil :remote-source-dir nil :restart-watch-directories nil :windows nil))
racket-before-run-hook
(racket-ansi-color-context-reset)
racket-browse-url-function
racket-browse-url-using-temporary-file
racket-command-timeout
10
racket-documentation-search-location
"https://docs.racket-lang.org/search/index.html?q=%s"
racket-error-context
medium
racket-expand-hiding
standard
racket-hash-lang-token-face-alist
((constant . font-lock-constant-face)
 (error . error)
 (other . font-lock-doc-face)
 (keyword . font-lock-keyword-face)
 (hash-colon-keyword . racket-keyword-argument-face)
 (at . font-lock-doc-face))
racket-history-filter-regexp
"\\`\\s *\\'"
racket-imagemagick-props
nil
racket-images-do-not-use-svg
nil
racket-images-inline
t
racket-images-keep-last
100
racket-images-system-viewer
"open"
racket-indent-curly-as-sequence
t
racket-indent-sequence-depth
0
racket-logger-config
((cm-accomplice . warning)
 (GC . info)
 (module-prefetch . warning)
 (optimizer . info)
 (racket/contract . error)
 (racket-mode-debugger . info)
 (sequence-specialization . info)
 (* . fatal))
racket-memory-limit
2048
racket-mode-hook
nil
racket-module-forms
"\\s(\\(?:module[*+]?\\|library\\)"
racket-pretty-lambda
nil
racket-pretty-print
t
racket-program
"/Applications/Racket v8.13/bin/racket"
racket-repl-buffer-name-function
nil
racket-repl-command-file
"/Users/oka_kurniawan/.emacs.d/racket-mode/repl.rkt"
racket-repl-history-directory
"~/.emacs.d/racket-mode/"
racket-repl-mode-hook
nil
racket-sexp-comment-fade
0.5
racket-shell-or-terminal-function
racket-shell
racket-show-functions
(racket-show-pseudo-tooltip)
racket-smart-open-bracket-enable
nil
racket-submodules-to-run
((test)
 (main))
racket-use-repl-submit-predicate
nil
racket-xp-add-binding-faces
nil
racket-xp-after-change-refresh-delay
1
racket-xp-highlight-unused-regexp
"^[^_]"
racket-xp-mode-lighter
(:eval
 (racket--xp-mode-lighter))

Minor modes

enabled
((auto-composition-mode)
 (auto-compression-mode)
 (auto-encryption-mode)
 (buffer-read-only)
 (display-line-numbers-mode)
 (editorconfig-mode)
 (file-name-shadow-mode)
 (font-lock-mode)
 (global-display-line-numbers-mode)
 (global-eldoc-mode)
 (global-font-lock-mode)
 (global-hl-line-mode)
 (ido-everywhere)
 (ido-ubiquitous-mode)
 (isearch-fold-quotes-mode)
 (line-number-mode)
 (mouse-wheel-mode)
 (projectile-mode)
 (recentf-mode)
 (save-place-mode)
 (semantic-minor-modes-format)
 (shell-dirtrack-mode)
 (show-paren-mode)
 (tool-bar-mode)
 (tooltip-mode)
 (transient-mark-mode))
Disabled minor modes
disabled
((abbrev-mode)
 (archive-subfile-mode)
 (auto-fill-function)
 (auto-fill-mode)
 (auto-save-mode)
 (auto-save-visited-mode)
 (blink-cursor-mode)
 (buffer-face-mode)
 (button-mode)
 (cl-old-struct-compat-mode)
 (column-number-mode)
 (comint-fontify-input-mode)
 (compilation-minor-mode)
 (compilation-shell-minor-mode)
 (completion-in-region-mode)
 (context-menu-mode)
 (cursor-face-highlight-mode)
 (defining-kbd-macro)
 (diff-auto-refine-mode)
 (diff-minor-mode)
 (dired-hide-details-mode)
 (doc-view-minor-mode)
 (doc-view-presentation-mode)
 (eldoc-mode)
 (electric-indent-mode)
 (electric-layout-mode)
 (electric-pair-mode)
 (electric-quote-mode)
 (global-prettify-symbols-mode)
 (global-semantic-highlight-edits-mode)
 (global-semantic-highlight-func-mode)
 (global-semantic-show-parser-state-mode)
 (global-semantic-show-unmatched-syntax-mode)
 (global-semantic-stickyfunc-mode)
 (global-visual-line-mode)
 (gnus-dead-summary-mode)
 (gnus-undo-mode)
 (header-line-indent-mode)
 (hl-line-mode)
 (horizontal-scroll-bar-mode)
 (hs-minor-mode)
 (ibuffer-auto-mode)
 (ido-cr+-debug-mode)
 (image-minor-mode)
 (indent-tabs-mode)
 (isearch-mode)
 (jit-lock-debug-mode)
 (lock-file-mode)
 (lost-selection-mode)
 (mail-abbrevs-mode)
 (menu-bar-mode)
 (minibuffer-electric-default-mode)
 (mml-mode)
 (next-error-follow-minor-mode)
 (org-cdlatex-mode)
 (org-list-checkbox-radio-mode)
 (org-src-mode)
 (org-table-follow-field-mode)
 (org-table-header-line-mode)
 (orgtbl-mode)
 (outline-minor-mode)
 (overwrite-mode)
 (paragraph-indent-minor-mode)
 (paredit-mode)
 (prettify-symbols-mode)
 (racket-smart-open-bracket-mode)
 (racket-xp-mode)
 (read-extended-command-mode)
 (semantic-highlight-edits-mode)
 (semantic-highlight-func-mode)
 (semantic-mode)
 (semantic-show-parser-state-mode)
 (semantic-show-unmatched-syntax-mode)
 (semantic-stickyfunc-mode)
 (sh-electric-here-document-mode)
 (shell-highlight-undef-mode)
 (size-indication-mode)
 (tab-bar-history-mode)
 (tab-bar-mode)
 (tar-subfile-mode)
 (temp-buffer-resize-mode)
 (text-scale-mode)
 (treesit-explore-mode)
 (treesit-inspect-mode)
 (undelete-frame-mode)
 (url-handler-mode)
 (use-hard-newlines)
 (vc-dir-git-mode)
 (vc-parent-buffer)
 (view-mode)
 (visible-mode)
 (visual-line-mode)
 (window-divider-mode)
 (xref-etags-mode))
greghendershott commented 5 months ago

You have a buffer for a .rkt file, and racket-mode is automatically enabled in that buffer; you can see Racket in the mode line for the buffer. Great!

Next, if you want to run that .rkt program, try using M-x racket-run. That should open (or reuse) a racket-repl-mode buffer, and run the program in it.


Using M-x racket-repl isn't intended to run a program. Instead it's a way to get a kind of "blank" REPL just to noodle around in. See https://www.racket-mode.com/#racket_002drepl.

M-x racket-repl should work from any buffer -- without giving you the error message that it works only in racket-mode or racket-hash-lang-mode buffers. I can't reproduce that; I don't get that error message. I'm trying to imagine how that could occur in your case... no theories quite yet.


TL;DR: I think maybe you just want to use racket-run (instead of racket-repl) and that will solve your "real", actual problem? OTOH what you report about racket-repl sounds like a bug; I just can't reproduce it quite yet.

greghendershott commented 5 months ago

One tiny point. I'm 99% sure it's unrelated to the problem you're reporting. Just FYI:

I installed racket-mode using package-install and set the following in my init.el.

(add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))
(setq racket-racket-program "/Applications/Racket v8.13/bin/racket")
(setq racket-raco-program "/Applications/Racket v8.13/bin/racket")

You just need:

(add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))
(setq racket-program "/Applications/Racket v8.13/bin/racket")

The racket-racket-program and racket-raco-program variables have been obsolete since 2017. Just racket-program suffices for the racket executable. See https://www.racket-mode.com/#Configure.

kurniawano commented 5 months ago

@greghendershott . Thanks for the tips. I removed the line on racket-raco-program. I can run M-x racket-run and the REPL appears. Yay.

However, M-x racket-repl still does not open blank REPL. This is what I did.

I'm not sure why. I think for run running "racket-run" works good for me. But I find it strange. I didn't encounter this another Mac machine which runs on Emacs 28. It works fine there to open blank REPL.

greghendershott commented 5 months ago

Thanks for the information!

As its doc string explains...

Show a Racket REPL buffer in some window.

The intended use of Racket Mode's REPL is that you find-file some specific file, then run it using a command like racket-run or racket-run-module-at-point. The resulting REPL will correspond to those definitions and match your expectations.

Therefore this racket-repl command -- which is intended as a convenience for people who want to "just get a quick scratch REPL" -- is actually implemented as running the file named in the customization variable racket-repl-command-file. When that file doesn't exist, it is created to contain just "#lang racket/base". You may edit the file to use a different lang, require other modules, or whatever.

... racket-repl works by running a .rkt file -- the one named by the customization variable racket-repl-command-file.

This defaults to ~/.emacs.d/racket-mode/repl.rkt, and is automatically created the first time if it doesn't exist.

Question: I wonder what happens if you try to open this file directly with M-x find-file -- does the buffer use racket-mode (do you see "Racket" down in the buffer's mode line)?


I didn't encounter this another Mac machine which runs on Emacs 28. It works fine there to open blank REPL.

Interesting. Maybe something changed after Emacs 28. I use 28.2 as my daily driver, which is what I tried.

I'll rebuild Emacs from source, which is version 30-something these days, and see if I can reproduce the problem, there.

kurniawano commented 5 months ago

@greghendershott , I can open repl.rkt and it contains the following.

;; Used by M-x racket-repl; you may edit
#lang racket/base

Somehow it didn't use racket-mode when I open the file but I can activate it after that using M-x racket-mode. Now I recall that sometimes when I open other .rkt file it didn't use racket-mode and I basically just manually activate it.

greghendershott commented 5 months ago

Thanks for trying this!

@greghendershott , I can open repl.rkt and it contains the following.

;; Used by M-x racket-repl; you may edit
#lang racket/base

That looks fine; it's the default.

Somehow it didn't use racket-mode when I open the file but I can activate it after that using M-x racket-mode.

That explains the error message.

Now I recall that sometimes when I open other .rkt file it didn't use racket-mode and I basically just manually activate it.

Oh, this happens sometimes in other situations? That sounds like the problem we should focus on. (It's very likely that fixing that will fix everything here.)


So: Weird. It looks like you've specified auto-mode-alist correctly. Why does that sometimes not work? Is something else "overriding" that? Let's look at the docs at https://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html.

When you visit a file, Emacs chooses a major mode automatically. Normally, it makes the choice based on the file name—for example, files whose names end in ‘.c’ are normally edited in C mode—but sometimes it chooses the major mode based on special text in the file. This special text can also be used to enable buffer-local minor modes.

Here is the exact procedure:

First, Emacs checks whether the file contains file-local mode variables. See Local Variables in Files. If there is a file-local variable that specifies a major mode, then Emacs uses that major mode, ignoring all other criteria. There are several methods to specify a major mode using a file-local variable; the simplest is to put the mode name in the first nonblank line, preceded and followed by ‘-*-’. Other text may appear on the line as well. For example,

; -*-Lisp-*-

tells Emacs to use Lisp mode. Note how the semicolon is used to make Lisp treat this line as a comment. You could equivalently write

; -*- mode: Lisp;-*-

You can also use file-local variables to specify buffer-local minor modes, by using eval specifications. For example, this first nonblank line puts the buffer in Lisp mode and enables Auto-Fill mode:

; -*- mode: Lisp; eval: (auto-fill-mode 1); -*-

Note, however, that it is usually inappropriate to enable minor modes this way, since most minor modes represent individual user preferences. If you personally want to use a minor mode for a particular file type, it is better to enable the minor mode via a major mode hook (see Major Modes).

This could override auto-mode-alist. However, we know that's not the case with the REPL command file example; its contents don't have this.

Second, Emacs checks whether the file’s extension matches an entry in any directory-local auto-mode-alist. These are found using the .dir-locals.el facility (see Per-Directory Local Variables).

:point_right: Do you use any .dir-locals.el files? If so could I please see an example?

Third, if there is no file variable specifying a major mode, Emacs checks whether the file’s contents begin with ‘#!’. If so, that indicates that the file can serve as an executable shell command, which works by running an interpreter named on the file’s first line (the rest of the file is used as input to the interpreter). Therefore, Emacs tries to use the interpreter name to choose a mode. For instance, a file that begins with ‘#!/usr/bin/perl’ is opened in Perl mode. The variable interpreter-mode-alist specifies the correspondence between interpreter program names and major modes.

When the first line starts with ‘#!’, you usually cannot use the -*- feature on the first line, because the system would get confused when running the interpreter. So Emacs looks for -*- on the second line in such files as well as on the first line. The same is true for man pages which start with the magic string ‘'\"’ to specify a list of troff preprocessors.

This is like the file-local mode in the -*- line, in the file contents. N/A for our primary example.

Fourth, Emacs tries to determine the major mode by looking at the text at the start of the buffer, based on the variable magic-mode-alist. By default, this variable is nil (an empty list), so Emacs skips this step; however, you can customize it in your init file (see The Emacs Initialization File). The value should be a list of elements of the form

(regexp . mode-function)

where regexp is a regular expression (see Syntax of Regular Expressions), and mode-function is a major mode command. If the text at the beginning of the file matches regexp, Emacs chooses the major mode specified by mode-function.

Alternatively, an element of magic-mode-alist may have the form

(match-function . mode-function)

where match-function is a Lisp function that is called at the beginning of the buffer; if the function returns non-nil, Emacs set the major mode with mode-function.

:point_right: What is your value for magic-mode-alist?

Fifth—if Emacs still hasn’t found a suitable major mode—it looks at the file’s name. The correspondence between file names and major modes is controlled by the variable auto-mode-alist. Its value is a list in which each element has this form,

(regexp . mode-function)

or this form,

(regexp mode-function flag)

auto-mode-alist, you seem to be setting correctly -- unless something else is later setting it wrong for .rkt??

Finally, if Emacs still hasn’t found a major mode to use, it compares the text at the start of the buffer to the variable magic-fallback-mode-alist. This variable works like magic-mode-alist, described above, except that it is consulted only after auto-mode-alist. By default, magic-fallback-mode-alist contains forms that check for image files, HTML/XML/SGML files, PostScript files, and Unix style Conf files.

Should be N/A?

Once a major mode is found, Emacs does a final check to see if the mode has been remapped by major-mode-remap-alist, in which case it uses the remapped mode instead. This is used when several different major modes can be used for the same file type, so you can specify which mode you prefer.

:point_right: What is your value for major-mode-remap-alist?

greghendershott commented 5 months ago

TL;DR:

  1. I have a commit a56a79d (not yet merged) that forces the racket-repl-command-file buffer's major mode to racket-mode, which should avoid any error message even if someone's configuration doesn't reliably/consistently do so for .rkt file buffers. I think that closes the reported issue, per se.

  2. At the same time, I'm happy to keep working with you to try to figure out what's going on with your configuration -- determine why it's not already doing this consistently/reliably. If you'd like to work on this, please start by answering some of my questions from my previous post (marked with :point_right:) , and we can take it from there!

greghendershott commented 5 months ago

I went ahead and merged the commit.


Someday if you have time, I'd be happy to help try to troubleshoot your configuration.

But if you're tired of this whole issue and want to move on, I'd understand that, too.

kurniawano commented 5 months ago

@greghendershott , sorry I was away for a few days. You are right. I wrongly set the paredit as major mode and it overwrite it. I have changed it to minor mode and now it always open .rkt files in racket-mode. I can run racket-repl also now. Thanks so much.

greghendershott commented 5 months ago

I wrongly set the paredit as major mode and it overwrite it. I have changed it to minor mode and now it always open .rkt files in racket-mode.

Oh I see, that makes sense.

Glad it's working for you now.

For me it was at least a chance to make racket-repl a tiny bit more "resilient", as well as dig into some Emacs docs and source code learning a bit more about exactly how major modes get picked.