-
-
Notifications
You must be signed in to change notification settings - Fork 93
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
Add a Scratch Buffer? #628
Comments
A couple initial reactions:
|
Using Unfortunately though, re: friction, the need to name scratch buffers is enough of an impediment that I use the REPL even for cases where a scratch buffer would be more appropriate, and then "graduate" to a saved scratch buffer when it becomes too inefficient. Even in this case, when I want to keep the file around, there's extra effort involved in renaming the
Interesting, yeah that makes sense. I suppose as long as the user can just start coding without needing to save a file and manage the names, that would still serve the purpose, if this feature were to be added. It would be ideal if the name of the file were completely abstracted somehow, though, as opposed to displaying as |
OK, I'll mull it over some more.
That shouldn't be a problem, in Emacs So I mean, I think you could sketch this out yourself (if you wanted) by (a) creating your |
Sounds good, I'll take a crack at it and share when I have something worth looking at, and we can see from there. |
One possible fit and finish detail: After creating such a buffer -- whose This would be independent of whatever the user has chosen for Although I'm not sure if that's part of your vision of the workflow, I wanted to point out how to do it if you want. (In my |
Here's a draft implementation making some decisions (not necessarily ideal) about some of the details. ;; TODO: Change to `defucstom'.
(defvar racket-scratch-file-name "~/scratch.rkt")
(defun racket-scratch-buffer ()
"Visit `racket-scratch-file-name' in a buffer named \"*scratch - Racket*\"."
(interactive)
(find-file racket-scratch-file-name)
(rename-buffer "*scratch - Racket*")
;; When buffer is empty because file was empty or didn't exist,
;; insert a reasonable initial default. (Thereafter, the user's
;; edits to the file are preserved, e.g. they can change the #lang
;; and other contents as they wish.)
(when (= (point-min) (point-max))
(insert "#lang racket")
(newline)
(newline))
(save-buffer)
;; Probably `racket-mode' due to .rkt extension, but to be sure:
(racket-mode)
;; Ignore whatever `racket-repl-buffer-name-function' just did to
;; set `racket-repl-buffer-name' and give this its own REPL.
(setq-local racket-repl-buffer-name "*scratch - Racket REPL*")) |
@greghendershott Cool, thank you for the example! I did start on a prototype but got interrupted - will get back to it and try to post something, hopefully later today or tomorrow 🙂 |
Oh, yeah, it wasn't supposed to be a nudge. 😄 No rush from my POV. Just had some time to think about it today and wanted to share in case helpful. |
Hey! https://github.com/countvajhula/racket-scratch This includes the following features:
WIP and planned features:
I haven't had a chance to thoroughly test it but I thought I'd share what I have for now. To use it, evaluate the So there you go! I realize there's a lot here, how would you prefer to proceed on this? Seems like we could either:
Of these, integrating it into Racket Mode would have the advantage of it being immediately available to all Racket Mode users. Arguably, this is a drawback as well, in case not every user wants this feature. Benefit of the second approach is that improvements could be done in a decoupled way and there would be a little more flexibility for experimentation and possibly adding support for other Lisps. On the other hand, it could be less discoverable by not being bundled. A third and more speculative but possibly flexible option could be to structure racket-mode itself in a kind of lib/test/doc manner, where there's a What do you think? |
This -- the combination of templates and versioning -- looks very cool! One initial reaction is that it's not limited to Racket or Racket Mode. Conceptually. And also, implementation-wise: The code has almost no reference to It looks like you're already thinking this way, what with the major mode to use being a var? So that leads me to think this should be its own Emacs package? Of utility to people using various programming languages? Or even authoring various non-program material, generally? That's not my final answer, just my dominating initial thought. [Even in that scenario, I'd be happy to help contributing to that package, if you wanted. And of course if you need some hook or API in Racket Mode, or the reverse (for Racket Mode to look for and use some hook in your thing), or whatever, would be happy to do that. And add it to "suggested packages for Racket Mode". And so on.] |
That's a great point - I hadn't thought about it as being usable even for authoring in non-programming settings. That would probably take some additional design input to generalize it to that use case, but it's a good one to plan for, even if it starts out as no more and no less than a Racket scratch buffer 😄 I think I agree with you that it might be better as a separate package for this reason. But yes, with use with Racket Mode being its primary usecase, would be great to ensure that it's convenient to set up for Racket users, and of course I'd be glad to have contributions from you, if you feel so moved! For now I'll plan to continue adding polish on an MVP for this and will touch base for any input or if any hooks are needed from Racket mode. |
Hey! Just an update here - I think the package should be in working shape, if you're curious to try it. I've renamed it to "mindstream" (after a similar concept from buddhist philosophy) and added straight.el instructions in the README: https://github.com/countvajhula/mindstream There's one big change that's needed before I'd call it ready, though, and that's to base the versioning on git instead of managing it at the Emacs + naive filesystem level. I'm gonna have to take a break from this to do a Qi release though, so I'll probably return to it in a week or so 🙂 |
Hey @greghendershott ! I took your advice to generalize it beyond Racket to any authoring setting -- text, markdown, scribble, whatever -- keeping it pretty lightweight so that most of the configuration would be done against the relevant major mode rather than for Mindstream specifically. I think it's shaping up to be quite a handy little tool. I find myself using it all the time to write meeting notes each week for the Qi project, to try out code samples and iterate on small implementations, even to draft emails, and, in fact, this message! If you have some time to try it out, I'd love to hear your feedback, and especially whether you think anything further could be done for it to integrate better with Racket Mode! I've made a note about having a dedicated REPL for the session buffer in the README -- please let me know if you feel that doesn't cover it. If we don't find anything terribly wrong at this point, I think we should be able to put it up on MELPA soon. |
Nice! I'll try to find some time to use it hands-on soon. Meanwhile, quick comments from reading the README:
|
Thank you, I've adopted those suggestions. One difficulty with the anonymous session path being in the Emacs folder is that it could become part of the containing |
There are packages that allow you to have multiple scratch buffers and persist them between sessions e.g. persistent-scratch with examples of how to extend it in https://umarahmad.xyz/blog/quick-scratch-buffers/ |
@countvajhula The new README looks good. As for the TODO comment about being platform independent, I think maybe you want to use |
@greghendershott Nice, looks like that'll do it!! |
@bestlem Thanks for the pointer. Looking into that, I found a bunch of other packages related to scratch buffers! Although there is some overlap, I would say that Mindstream is quite different from these packages. Crucially, it's versioned, meaning that your entire history of changes is preserved. This gives rise to the organizing concept of a session. A session is a record of work on some topic or a snapshot of how you were thinking about a project at a certain time. For instance, a session could be you writing a blog post, or learning about a Racket library like megaparsack, or learning about macros, or solving a programming challenge. In addition to sessions providing features designed to help you be more efficient (like "Live mode"), over time, you'd amass a collection of such sessions that tend to be valuable as records, like old notebooks. Now, the versioning provided by Mindstream isn't implemented in the package but is actually provided by Git! This does two things: (1) it keeps mindstream lightweight, and (2) it opens up a whole world of possibilities for harnessing the Git ecosystem and features, and plugins that already exist and which may be written in the future (e.g. Magit and Git-timemachine). These things together make the package pretty handy for basic scratch buffers, but mean that there is potential for a lot more, and I feel we've only scratched the surface, so to speak :). If you have a moment, please try it out and let us know what you think. |
As you know I've opened a couple issues on its repo. Will do that going forward. As for this issue here: I think the actionable item with which to close it, would be to update any Racket Mode docs that discuss "recommended other packages". I'm happy to go ahead and do that pointing to your GitHub repo. Or, if you prefer I can wait and do this after it's available on MELPA. Just let me know what you prefer; not urgent. |
Thank you so much for the thoughtful feedback so far! All that sounds good. I'll go ahead and submit a PR to add it to MELPA in the coming days and will keep you posted. |
One last thing before I put it up on MELPA. I've been considering the name "freewrite" for the package. Mindstream is a cool name, but I wonder if "freewrite" conveys more specifically what you would use it for, without having to read the docs. This name perhaps loses the "session" aspect encoded in the present name, but arguably it's only present in retrospect rather than when you first encounter the name... if that makes any sense. Googling "freewrite," I found a kickstarter for a device that has the same name. Quite a different thing and I'm not sure if that is a well-known device, but I wouldn't want users to feel that this package has something to do with that. Probably not something to worry about. But what do you think? Do you have any preferences on the name? |
Like they say, naming things is hard. I hear there's a new package to defer naming files:
If only such a thing existed for naming packages. 😛 Seriously I'm of the school that a name needn't mean much. Almost any name is OK if most people can remember, spell, and pronounce it. If the product/project succeeds, people will accept any name. If it doesn't succeed, the name won't matter. Not to date myself but: "VisiCalc" was a descriptive name for a spreadsheet. Later, "Lotus 1-2-3" was a weird, no-meaning name -- and the product was a huge hit, and no one cared about the name. (Later they didn't care because they'd switched to "Excel".) IMHO "Mindstream" is good. So would be the name of a pet, or a science fiction character, or anything really. If they need/like the project, people won't even "hear" the name after the first 5 minutes, it's just another label. |
p.s. That's not to say I think there's anything wrong with "freewrite"; it's good, too! Also I'm not dissing a creative pun, or use of Latin or French (e.g. some riff on "déjà vu"? like instead of "already seen", "already named/saved/xxx"). But in this case I'm just saying I'm not clever or patient enough to do so. :) Also some of those might run afoul of "tricky to spell and Google" for some of us. |
Alright, "Mindstream" it is then, and I've submitted it to MELPA! Look at that, PR number 9000. Maybe we should call it "Mindstream 9000" 🤔 😆 |
Hey @greghendershott ! Any chance you can attend the Racket meetup tomorrow? I'm planning to give a short demo of Mindstream. Would be great to see you there! |
Unfortunately I'm not free then. 😞 I hope the demo goes well! I'd love to watch a video of it later, if available. Also look forward to meeting someday IRL or virtually. |
@greghendershott Thank you, and yes that would be great!! I might make a trip out to Boston sometime, or at least, to Seattle for RacketCon this year. Come to RacketCon 😄 |
Did the demo today and it went well, I think! There was an inquiry about whether Mindstream could be used in other editors besides Emacs. Have you ever thought about writing cross-editor extensions? Not sure how feasible it would be. |
Update: the MELPA PR was merged so this is "officially" out 😄 |
One workflow that I like is the idea of a "scratch buffer." That is, a buffer that you can quickly visit, put some code in and evaluate to see what happens. Many IDEs support something like this, including Emacs (the usual scratch buffer), Dreampie for Python, Groovy Console for Groovy, and of course, DrRacket's definitions window, where you can enter a bunch of code and then hit Run.
I have a similar workflow configured in Emacs, where I open a scratch buffer named
*scratch - Racket*
withracket-mode
as the major mode. I can evaluate individual expressions in this buffer if I happen to have a REPL open, but what I'd like to be able to do is run this buffer without needing to save it to disk (the same way as with DrRacket). That way, I could just clear the contents upon visiting the buffer, and enter some fresh code in and have it evaluated from scratch each time, and being able to easily edit errors and re-run as needed. I find this helpful for quickly validating assumptions or trying things or initial prototyping without the "commitment" of having a saved file yet, and where I can treat it as a cohesive program (and not just individual expressions to edit with varying dynamic state as in the REPL). But at the moment, attempting torun
this makeshift scratch buffer prompts to save the file -- which makes sense usually, but not for the UX I'm going for here.Would it make sense to add a Scratch Buffer to Racket Mode? If you think so, some of the links above could provide some design ideas for iterating on this feature in Racket Mode - Dreampie in particular has some good ideas.
The text was updated successfully, but these errors were encountered: