Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Buffer-specific back end? #656

Open
countvajhula opened this issue Apr 4, 2023 · 5 comments
Open

Buffer-specific back end? #656

countvajhula opened this issue Apr 4, 2023 · 5 comments

Comments

@countvajhula
Copy link

Hi! I'm attempting to try out a Rhombus scratch buffer in mindstream, and it needs to use the bleeding edge Racket as its back end. For all other Racket buffers (which all start in /var/tmp/...), I'd like to use a different (i.e. the default system Racket) back end.

I know that we can configure which back end to use based on the base directory path, but is it also possible to declare a backend for a specific buffer, since in the present case, all of these buffers would start at the same path? For instance, if we could set a buffer-local variable to indicate the back end to use, I think that should work for my use case, as I would be able to set it at buffer creation time based on the user's indicated needs (e.g. whether they are starting a Rhombus or a Racket or some other session). Wdyt?

@soegaard
Copy link
Contributor

soegaard commented Apr 4, 2023

I believe the evaluator is shared between buffers, so it's a non-trivial change.
The here-and-now solution must be to open two different Emacs instances.

@greghendershott
Copy link
Owner

When developing multi back ends, I initially followed the example of racket-repl-buffer-name being a buffer-local variable: racket-back-end was in fact a buffer-local variable.

But that turned out not to be feasible, so racket-back-end became a function instead of a buffer-local variable. (Why not feasible? Well I don't immediately recall. My brain is deep in "pdb" stuff. This is a lazy answer. I can dig deeper, later, if you need -- sorry!!)

One quick idea: IIRC the racket-back-end function mainly keys off the value of default-directory, which is a buffer-local variable. It can be non-nil even when buffer-file-name is nil. So I think you could set it for a non-file, scratch-like buffer? Maybe default-directory gives you leverage for a hack? And if that works, but isn't ideal for some reason, we could add a new, official variable.

@countvajhula
Copy link
Author

All good, please keep your head where it needs to be, and looking forward to whatever pdb is!

For whenever you're spending time on Racket Mode next, I tried a couple of things and this hack appears to work:

;; while creating the buffer (which is saved on disk from the beginning so it has an actual path and filename fwiw)
(setq-local racket-buffer-back-end
                (list
                 :directory            default-directory
                 :racket-program "~/work/racket/racket/racket/bin/racket" ; the source repo version of Racket
                 :remote-source-dir nil ; just some default values copied over from an existing entry in racket-back-end-configurations
                 :repl-tcp-accept-host "127.0.0.1"
                 :repl-tcp-port        0
                 :restart-watch-directories nil
                 :windows              nil))

racket-back-end seems to be the main entry point in Racket Mode for getting the relevant backend for the buffer, so I added an overriding check for the presence of a defined buffer local variable.

And now, racket-run from a scratch buffer does load the correct back end.

As you mentioned that relying on a buffer local as the primary means to determine a backend didn't work (maybe something to do with the many different local vs remote configurations supported?), maybe using a buffer-local as an overriding configuration like the above hack would be reasonable? That is, if the variable happens to be set, then use it, otherwise fall back to the other means of determining the appropriate back end. In this case, it would probably make sense to extend the racket-add-back-end API (or introduce a new interface) to support specifying a one-off rather than directory-oriented backend.

@greghendershott
Copy link
Owner

Fortunately I kept around an old, un-squashed branch with more commit history details for just this sort of situation. 😄

This is the commit where it changed from a buffer-local variable to a function. Some explanation in the commit message:

Change racket-back-end from a buffer-local variable to a function that
is called whenever we need a property list value.

The old way, each buffer would need to setq-local the var, which was a
nuisance.

Worse, it left the configuration "baked into" each buffer -- it
wouldn't be refreshed until the buffer re-visited a file or was
recreated. This was super confusing when experimenting with
configuration changes, but buffers would still be using the old
values tucked away into the old racket-back-end buffer-local var.

Now, with this commit, every use of a property list value is
effectively an on-demand function from `default-directory' to the
property list, so it will always be "fresh" and reflect the latest
configuration.

I wanted to go ahead and share this in case it made sense to you. Although I don't have the spare brain capacity to dig into it deeply, myself, right now, I can still do that later if that would help you!

@greghendershott
Copy link
Owner

greghendershott commented Apr 5, 2023

A bit more thought:

The nuisance and drawbacks I discovered after dog-fooding it, I think are real for the general case:

  • Multiple major modes (like a half dozen in Racket Mode that need a back end, racket-mode, racket-repl-mode, racket-logger-mode, racket-debug-mode, and more) needing to setq-local this or something else indirectly might not work.
  • Updating a configuration used by potentially many live buffers leaving them mysteriously not picking up the changes until the buffers get re-created. That was super frustrating as an end user.

But, maybe that doesn't apply for the special case where you have one special mode for exactly one live buffer... if that's your situation? And so maybe your overriding check is fine for your special case? And anyway you definitely need something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants