clojure-emacs / cider

The Clojure Interactive Development Environment that Rocks for Emacs
https://cider.mx
GNU General Public License v3.0
3.54k stars 646 forks source link

Project-specific `*cider-<x>*` buffers #3427

Open daveliepmann opened 1 year ago

daveliepmann commented 1 year ago

When running CIDER on multiple separate projects, buffers like *cider-result* and *cider-error* of one project behave as if they are in the directory of another project. This surprising behavior is seen with pwd and find-file, among others.

Instead of such global CIDER buffers, each CIDER instance should instead have its own *cider-error*, *cider-result*, and so on.

The relevant principle is that one CIDER should have nothing to do with any others. Seeing the wrong directory can be distracting or confusing, and makes some common tasks frustratingly manual and slow. For instance, copy-paste from the result buffer into a resource file should be a couple keystrokes, but if another project's directory pops up when I find-file, suddenly I must navigate through half my file system.

This is especially noticeable for folks who keep a playground REPL running independent of a specific project, or who as freelancers are working on multiple client projects.

Steps to reproduce

To see this in action, start a REPL in each of two projects. Then (throw (Exception.)) from one and then the other. From the *cider-error* buffer of the second, pwd will report that it is in the directory of the first.

I initially wrote this up as a *cider-result*-specific bug. The details may be useful:

*cider-result*

Expected behavior

Regardless of other CIDER REPLs running or the order of execution of forms in any of them, *cider-result* should behave (in terms of find-file, dired, etc.) like a buffer related to the project it was produced from.

Actual behavior

The first cider-pprint-eval-last-sexp in any CIDER instance sets the directory used by pwd/find-file/dired in all CIDER projects' *cider-result* buffers.

Steps to reproduce the problem

  1. have or create two separate project directories, A and B, with no other CIDER instances running
  2. cider-jack-in from project A and cider-pprint-eval-last-sexp a form
  3. cider-jack-in from project B and cider-pprint-eval-last-sexp a form
  4. pwd from *cider-result* (which is a result from project B) says it is in project A

Note that the order of cider-eval-last-sexp and cider-jack-in are irrelevant. The determining factor is the project one is in the first time each given buffer (e.g. *cider-result*, *cider-error*) is created.

vemv commented 1 year ago

Interesting!

I cannot help thinking - shouldn't it be clear enough that *cider-result* always refers to whatever you evaluated last?

Would it be possible for you to share a screenshot showing how things look for you?

There's the possibility that this can considered to be simply a buffer/window/project management problem.

For instance, in my personal setup I have some code that closes *cider-error*, if present, whenever I switch to another project.

bbatsov commented 1 year ago

I intentionally made a lot of those buffers generic to avoid the complexity of having them be project-specific. It didn't seem to me transient buffers like results, docs and so on have much value to be kept around. (and of course you can manually rename something to keep it around when needed)

Anyways, I'm open to discussing the topic in case there are some compelling use-cases for this.

daveliepmann commented 1 year ago

Would it be possible for you to share a screenshot showing how things look for you?

Sure!

Minimal reproduction

Minibuffer is the result of pwd and points to an unrelated project.

Screenshot 2023-08-23 at 19 36 31

Use case 1

Here is an actual point of friction which I encounter relatively often.

  1. I evaluate some form and it throws. Note that focus automatically switches to *cider-error*.
  2. I scan the stacktrace and think a moment. Perhaps I step away to the hammock, fingers properly away from the keyboard in approved Clojure debugging style.
  3. Enlightenment – return to keyboard – dired, to zip immediately to the source of the problem – WTF? Oh, right, *cider-error* was taken by that other project yesterday. What was I doing again?
Screenshot 2023-08-23 at 20 13 22

Use case 2

Here is an actual point of friction which I encounter relatively often.

  1. CIDER's result buffer has long ago been assigned project X
  2. In project Q, I eval some data. After scanning it for a moment, I decide to select a portion, copy it, and put it in a project Q file.
  3. ido-find-file situates me in project X. This isn't just inelegant, it's genuine friction: I must delete 4x before navigating carefully back to project Q's directory
  4. oops, I forgot, I've been trying to retrain my fingers to use projectile! I'm sure it will do the right thing. C-c p f (projectile-find-file) brings me this helpful minibuffer dialogue: [<project X>] Find file: <a bunch of files unrelated to what I'm doing>
Screenshot 2023-08-23 at 19 39 53 Screenshot 2023-08-23 at 19 40 01 Screenshot 2023-08-23 at 20 02 38
vemv commented 1 year ago

Thanks for the screenshots! It's always good to learn about how a variety of programmers work.

Use case 1

the stacktrace itself can inform you about the context about what you were doing. It typically should have at least one stack frame which is related to a specific project of yours.

Note that in the upcoming CIDER 1.8.0, more internals will be hidden under the tooling filter, so the relevant frames will be easier to locate.

(you can try that right now by using cider-nrepl latest - no other changes needed)

Use case 2

It seems to boil down to the fact that *cider-result* has a default-directory. Perhaps we can set it to nil.

OTOH, it sounds like you are relying on this implementation detail as part of your workflow?

It seems fairly simple to move to a buffer of project Q before performing ido-find-file.

Alternatively, you could have a hook such that whenever you switch projects, you check for any possibly present *cider-result* buffer (or similar ones) and alter their default-directory to match your new project.

And yet another alternative (less intrusive one) would be to advice-add 'ido-find-file :before such that the default-directory is bound to your current project if the current buffer's name starts with *cider.

Cheers - V

daveliepmann commented 1 year ago

I don't think we are on the same page regarding use case 1. I know which project I'm on. CIDER acts as if it's on a different one. What are you saying would be improved by reading the stacktrace better?

The issue in step 3 is not the confusion but the fact that dired situates me in the wrong place because CIDER leaks context from another project. Even if the user knows what's going on, it's bad design to force them to navigate from an unrelated project back to the context they're obviously in.