# DrRacket Workspaces?

**URL:** <https://racket.discourse.group/t/drracket-workspaces/2025>\
**Category:** General\
**Tags:** drracket\
**Created:** [June 19, 2023, 2:29pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025 "2023-06-19T14:29:24Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![madkins23](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/madkins23/32/1208_2.png) [@madkins23](https://racket.discourse.group/u/madkins23)\
**Post date:** [June 19, 2023, 2:29pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/1 "2023-06-19T14:29:24Z")

</div>

I would like to start a conversation about adding workspaces to `DrRacket`.

Workspaces are (in my experience) a common feature in modern IDEs:

- VSCode calls them "workspaces" and
- the JetBrains family of IDEs (e.g. `IntelliJ`, `Goland`, `Android Studio`) call them "projects".

I'm going to define a workspace as providing the following (probably incomplete) set of features:

- Defining a directory containing project files.
- Starting from the workspace directory when saving newly created files.
- Providing one or more views showing the file and/or project structure.
- Remembering open files and reopening them when the IDE is restarted.
- Tracking other workspace preferences as appropriate.

Currently there are some plugins for `DrRacket` that provide some of these features:

- [`files-viewer`](https://pkgs.racket-lang.org/package/files-viewer) provides:
  - naming of directory as a "workspace"
  - `File Manager` view showing directory structure

- [`drracket-workspaces`](https://pkgs.racket-lang.org/package/drracket-workspaces) provides:
  - ability to a set of open files by "workspace" name
  - but:
    - there is no update to an existing workspace and
    - an existing workspace can't be deleted by name, all must be cleared at the same time

- [`drracket-restore-workspace`](https://pkgs.racket-lang.org/package/drracket-restore-workspace) provides:
  - reopening of files from the last shutdown of `DrRacket`

I have some concerns about implementing workspaces as part of a plugin as opposed to a first-class addition to `DrRacket`:

- Saving a new file seems to be part of core `DrRacket` functionality and may not be simple (or possible) for a plugin to hook into.
  - [I've asked on this discourse about trapping the save to automatically indent all files pre-save](https://racket.discourse.group/t/is-there-a-way-to-get-drracket-to-indent-all-on-save/2009).\[1\]
  - It might be useful to provide a way to hook QuickScripts into the save process.
  - JetBrains IDEs provide both `Actions on Save` and `File Watchers`, the latter looking for immediate changes without a file save (or something like that).

- There may need to be some support in the `DrRacket` core for per-workspace preferences.
- It just seems useful to integrate something like workspaces into the `DrRacket` core (or at least discuss it as an option).

These concerns may well stem from an inadequate understanding of the plugin API on my part. Or it may be that some minor changes to the plugin API would make it possible for plugins to support workspaces.

That's all I have to say for now. I thought this post might start a discussion, and if not no big deal.

* * *

1. This is probably the most annoying `DrRacket` behavior I personally encounter on a regular basis. I'm running Ubuntu Linux. If I start `DrRacket` from my project directory it works fine (the file chooser starts in that directory) but I typically launch `DrRacket` from an icon on my launcher bar. Every time I go to save a file for the first time I must navigate down from my home directory. Not the end of the world, but a bit irritating (over and over again).

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [June 20, 2023, 4:09pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/2 "2023-06-20T16:09:04Z")

</div>

Read the paragraph "Racket turns extra-linguistic mechanisms into linguistic constructs." to see why "projects" aren't popular in Racket.

> **[manifesto.pdf](https://www2.ccs.neu.edu/racket/pubs/manifesto.pdf)**
>
> 9.56 MB

I seem to recall discussions on the mailing list on the topic, but I couldn't locate them.  
Maybe someone else with better memory can direct you to the old discussions.

Some features like a "file manager" to quickly find files in the directory structure  
doesn't conflict with the manifesto. Screen sizes have grown and reserving  
screen estate for such a thing is no longer a problem.

Note that normal Racket programs normally don't have the excessive number of files  
that some programming languages do (like Swift where the convention is that each class and each extention get a separate file). Openening the handful of files you are actively working on  
and using tabs to switch between them (use cmd-1, cmd-2 etc to switch between them)  
seem to work fine in most cases.

> - Remembering open files and reopening them when the IDE is restarted.  
> That's easily solved - don't close DrRacket 😉

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [June 21, 2023, 7:07am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/3 "2023-06-21T07:07:26Z")

</div>

There's also a simple `workspaces` quickscript listed on this page:

> **[Quickscript Scripts for DrRacket](https://github.com/racket/racket/wiki/Quickscript-Scripts-for-DrRacket)**
>
> The Racket repository. Contribute to racket/racket development by creating an account on GitHub.

It merely has menu items to save/restore set of opened files. Since a workspace is saved into a file, several workspaces can be defined.

* * *

At the link above there's also an `Open recent` quickscript, which I use all the time (while I don't use workspaces usually). It improves on DrRacket's open recent menu item:

- It has a search box
- It can open multiple files at once by unchecking the check box at the bottom
- It can be used to switch between tabs.

The script doesn't have a key shortcut by default, but I change it to `ctl-alt-o` by adding:

```scheme
  #:shortcut #\o
  #:shortcut-prefix (ctl alt)

```

below `#:label`.

* * *

At the link above there is also a `new file in same directory` quickscript, which should appease your frustration of going back to the home directory when saving a new file.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [June 21, 2023, 7:26am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/4 "2023-06-21T07:26:11Z")

</div>

Also, if you turn your project into a package/collection you have the following benefits:

- You can use the `File|Open require path...` (which has a search box) and type the project name to quickly find a file even in a subdirectory
- You can run `raco setup my-project` and `raco test my-project` from anywhere, which compiles/checks the whole project at once (and `compile-omit-paths`, `test-omit-paths` can be specified in an `info.rkt`)
- You can use ` require my-project/subdir/file` (usually within a module that's not part of the project itself)

To make it a collection: In the parent directory of `my-project`, type:

```scheme
raco pkg install --link my-project

```

Although your life will be even more joyful if you start your project with `raco pkg new my-project` to create a new directory pre-filled with yummy goodies (scribble docs, license, readme, info.rkt, …). If you want to publish your package on the website, you should definitely do that.  
For an existing project it may involves something like

```scheme
mv my-project my-project2 && \
raco pkg new my-project && \
mv my-project2/*.rkt my-project

```

More info on packages: [Package Management in Racket](https://docs.racket-lang.org/pkg/index.html)

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [June 21, 2023, 1:02pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/5 "2023-06-21T13:02:30Z")

</div>

Fun shell fact, the line continuation backslashes are not needed if the line ends in `&&` (or `|`, or `||`).

---

<div class="post-metadata">

**Author:** ![spdegabrielle](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/spdegabrielle/32/95_2.png) [@spdegabrielle](https://racket.discourse.group/u/spdegabrielle)\
**Post date:** [June 21, 2023, 6:19pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/6 "2023-06-21T18:19:55Z")

</div>

> [@soegaard](#):
>
> Racket turns extra-linguistic mechanisms into linguistic constructs

It’s worth quoting

> 1. Racket turns extra-linguistic mechanisms into linguistic constructs.When programmers must resort to extra-linguistic mechanisms to solve a problem, the chosen language has failed them. Even if it is not always obvious how to fix such failures, programming language researchers ought to accept the general idea and try to work on finding the proper linguistic mechanisms. Due to Racket’s uses, the language currently internalizes several resource-management mechanisms that are often found in the underlying operating system. Similarly, this philosophy prohibits the idea of “projects,” as found in other IDEs, because this also externalizes resource management, linking, and other aspects of program creation.

But so is the aside

> This guideline does _not_ mean that linguistic constructs ought to replace _all_ tools. It merely means that the creation of every tool must raise the question whether it should be a tool or a part of the language. Some tasks are best left to tools, others are better realized as extensions of the language. Finding a good balance is a difficult problem. For example, the creator of a Racket library or a large system may very well wish to think in terms of projects, but a novice student must never have to say “create project” before writing and running a “hello world” program

On my wish list is a _DrRacket Professional Edition_ with all the plugins and quickscripts (and templates browser like **.net** ) - but I’m not sure about projects because I like not having to make a project.

---

<div class="post-metadata">

**Author:** ![madkins23](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/madkins23/32/1208_2.png) [@madkins23](https://racket.discourse.group/u/madkins23)\
**Post date:** [June 21, 2023, 10:05pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/7 "2023-06-21T22:05:25Z")

</div>

I wouldn't want to make workspaces/projects/whatever _necessary_ in order to use `DrRacket` (or `Racket` for that matter). It's just that there are potentially advantages to having something of the sort.

I typically jump from one thing to another (likely due to a combination of retirement and ADHD). When I go back to a previous project or workspace it's convenient for me to have the IDE remember what I was doing the last time, what files were open, what commands and tests I had configured. It saves me time and mental churn.

Yes, some of the languages I use have project-level semantics built in. Sometimes that's convenient and sometimes it's a pain, but it comes with the language, not the IDE.

That's not at all what I'm suggesting. I'm just looking at `DrRacket` as a great tool that is missing some helpful conveniences that sort of group together in my mind as a "workspace".

---

<div class="post-metadata">

**Author:** ![gus-massa](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gus-massa/32/507_2.png) [@gus-massa](https://racket.discourse.group/u/gus-massa)\
**Post date:** [June 22, 2023, 1:41am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/8 "2023-06-22T01:41:09Z")

</div>

Somewhat related: I used WinEdt a lot to edit LaTeX files. A very handy feature was to declare one of the files in the editor the main file. The idea was to be able to edit multiple files simultaneously, and when you hit the "compile" button, all the files are saved and the LaTeX compiler is run on the main file, that (probably) includes all the other files you are working on.

I was recently working with three LaTeX files simultaneously in other editor, and I had some problems with the layout of a table that was defined not in the main file. So I had to make the fixes, remember to switch to the main file, and hit the compile button there. It was painful because half of the times I forgot to switch the file and got a nasty error.

I had a similar problem with Python a few weeks ago. I had the main file, and a file with helper functions, and debugging/fixing the helper functions was painful because I had to switch to the main file to run it.

Also, a trick that I used in WinEdt was to use a .bat file as the main file, so I could run arbitrary code, like compiling a file in fortran and then running it with an input in a .txt file, or perhaps compiling and chaining a few files. The advantage was that I can edit all the files simultaneously and when I hit the compile button, then all are saved and compiled/executed/whatever and it was very easy to write the details in the .bat file.

The disadvantage was that WinEdt has too many options to configure what happens when you hit the run button. The defaults for the usual files are good, but adding handlers for new extensions is not newbie friendly.

So my feature request, is to be able to mark a file as the main file, and make the "run" button run that file instead of the file in the selected tab.

---

<div class="post-metadata">

**Author:** ![spdegabrielle](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/spdegabrielle/32/95_2.png) [@spdegabrielle](https://racket.discourse.group/u/spdegabrielle)\
**Post date:** [June 22, 2023, 10:30am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/9 "2023-06-22T10:30:03Z")

</div>

> [@gus-massa](#):
>
> So my feature request, is to be able to mark a file as the main file, and make the "run" button run that file instead of the file in the selected tab.

I like it but feel a beginner could get in a state where they re hitting run but it is not running the tab they expect and getting confused.

- Maybe put a run button on each tab? or on tabs that don't have `(provide ...)`'s ?

A related difference between DrRacket and other IDE's is the meaning of the 'Run' button:

- Other IDE's often have a distinct Run and Debug buttons.
- In DrRacket Run is the same as Debug on other IDE's. (and contributes to complaints about Racket being slow)

If someone wants 'Run' like other IDE's their only option is to open a comment line and type

```scheme
Racket myfile.rkt

```

You can of course turn off debugging and profiling, but that is hidden behind a menu, and we never suggest it because there is still a performance cost to running from DrRacket.

---

<div class="post-metadata">

**Author:** ![madkins23](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/madkins23/32/1208_2.png) [@madkins23](https://racket.discourse.group/u/madkins23)\
**Post date:** [June 22, 2023, 12:37pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/10 "2023-06-22T12:37:43Z")

</div>

The JetBrains IDEs (`IntelliJ`, `Goland`, `Android Studio`, etc.) provide a way to configure a variety of "run" and "test" configurations. They appear in a dropdown. The "run" and "debug" icons just activate the current choice.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [June 22, 2023, 1:36pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/11 "2023-06-22T13:36:46Z")

</div>

It seems that this behaviour can be overridden actually:  
[https://docs.racket-lang.org/tools/drracket\_unit.html#(meth.\_(((lib.\_drracket%2Ftool-lib..rkt).\_drracket~3aunit~3aframe~25).\_execute-callback))](https://docs.racket-lang.org/tools/drracket_unit.html#%28meth._%28%28%28lib._drracket%2Ftool-lib..rkt%29._drracket~3aunit~3aframe~25%29._execute-callback%29%29)

So a DrRacket plugin should be able obtain this behaviour. (or hopefully the upcoming Quickscripts hooks).

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [June 22, 2023, 2:10pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/12 "2023-06-22T14:10:26Z")

</div>

> [@gus-massa](#):
>
> So my feature request, is to be able to mark a file as the main file, and make the "run" button run that file instead of the file in the selected tab.

One thought I've had along these lines would be to make a set of open files (maybe all the tabs in one frame?) share their program state in the sense that each separate interactions window was working with the same program, but with the bindings from the corresponding definitions window available to it. So hitting "Run" on any one of them would effectively run all of them and let you explore what was going on everywhere. (There are some issues with IO and perhaps other things to think through.)

---

<div class="post-metadata">

**Author:** ![gus-massa](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gus-massa/32/507_2.png) [@gus-massa](https://racket.discourse.group/u/gus-massa)\
**Post date:** [June 23, 2023, 8:18pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/13 "2023-06-23T20:18:00Z")

</div>

I prefer that only the main tab runs (with whatever definition of run it has). It fit's better **my** mental model. The main program may require the other files (perhaps in different phases!), r the other files may be data files like a txt.

I remember in VB6, that you can open "groups" that has multiple "projects", each project has multiple files. The main project was the program, and the other projects were dll. So the run button first "run" the dll, register them in the magic COM world[1], and then the main program used them. IIRC the interaction windows was connected only to the main program.

> [@spdegabrielle](#):
>
> I like it but feel a beginner could get in a state where they re hitting run but it is not running the tab they expect and getting confused.

Yep. IIRC in WinEdt it was not super clear if you had defined the main file (and the run button was running that file), or the main file was undefined (and the run button just compile the tab that was visible). It was some subtle difference on the icons (grey vs dark green?) that was sometimes very confusing.

[1] And complained if you were not an administrator.

---

<div class="post-metadata">

**Author:** ![sschwarzer](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/sschwarzer/32/1940_2.png) [@sschwarzer](https://racket.discourse.group/u/sschwarzer)\
**Post date:** [June 24, 2023, 6:01am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/14 "2023-06-24T06:01:28Z")

</div>

> [@spdegabrielle](#):
>
> or on tabs that don't have `(provide ...)`'s ?

A module may have a [main or test module](https://docs.racket-lang.org/guide/Module_Syntax.html#%28part._main-and-test%29) that should be run, so having the "Run" button disappear for those modules would be very inconvenient (and in my opinion quite confusing if you don't know the reason for the disappearance).

---

<div class="post-metadata">

**Author:** ![maueroats](https://avatars.discourse-cdn.com/v4/letter/m/c0e974/32.png) [@maueroats](https://racket.discourse.group/u/maueroats)\
**Post date:** [June 25, 2023, 10:52pm UTC](https://racket.discourse.group/t/drracket-workspaces/2025/15 "2023-06-25T22:52:12Z")

</div>

> [@gus-massa](#):
>
> I prefer that only the main tab runs (with whatever definition of run it has). It fit's better **my** mental model.

Robby's point in saying "with the bindings from the corresponding definitions window available to it" is that if a file does not `provide` certain functions, you cannot access them if all you have is an interaction with the "main" tab.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [June 26, 2023, 9:08am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/16 "2023-06-26T09:08:01Z")

</div>

Here's a proof-of-concept quickscript that open/switches to "main.rkt" in the same directory and runs the interactions.

> <https://gist.github.com/Metaxal/2a57a6788028b98535ab1aabb0b3e1aa>

To try it (after installing it and "Scripts|Manage scripts...|Reload menu"), click on `Scripts|Run main file test` and follow the instructions.

This assumes that "maink.rkt" is always the main file in the directory, but I suspect you don't want to be bound to this name.  
This would require either:

- to save the main filename to disk
- or to mark the main file every time DrRacket is started (and make the script `#:persistent`)

Optionally:

- a "Go back" button/menu item could go back to the original tab before the tab switch
- instead of a menu item, it could be a button next to the "Run" button. A DrRacket plugin would also be able to override Run, but I'm not sure that's desirable here, as one may want to also retain the Run per file behaviour.

I'm not sure how much of this is aligned with what you want – let me know.

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [July 3, 2023, 2:39am UTC](https://racket.discourse.group/t/drracket-workspaces/2025/17 "2023-07-03T02:39:00Z")

</div>

> [@gus-massa](#):
>
> I prefer that only the main tab runs (with whatever definition of run it has). It fit's better **my** mental model.

This does make sense to me too; my thinking was (a few steps beyond and not clearly explained!) more along the lines of what to do with the interactions windows of the window where you are editing and hit the "Run" button. My thinking was that running the "main" program would eventually require the file that you're editing (otherwise, why are you running that one and editing this one?), so then you'dbe interested in what's going on in that module and so getting an alternative view on your program by doing stuff in the interactions window of the file you happen to be editing in would be helpful.

You do raise a good point about requires that cause other, non-main files to be instantiated multiple times in multiple phases (other strange things will happen with `dynamic-require` and `current-namespace` and friends) but I feel pretty good that we could figure something out that would work well and not be confusing.

Anyway, I've had this thought for a very long time but not found the time to act on it, so we don't need to worry about me breaking anything anytime soon! 🤣
