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

RFC - Project Selector #2823

Closed
benwainwright opened this issue Dec 12, 2020 · 7 comments
Closed

RFC - Project Selector #2823

benwainwright opened this issue Dec 12, 2020 · 7 comments
Labels
A-workspace Area: Overall UX, editor layout, tabs/groups/splits etc. enhancement New feature or request

Comments

@benwainwright
Copy link

benwainwright commented Dec 12, 2020

Hi there!

So I've recently checked out the application and as I mentioned to @bryphe on another issue, I'd like to start contributing. The thing that I'd really like to see in Oni2, which would probably tip me into using it as my main workhorse is the project selection feature suggestion I describe in #1914 (comment). If its ok, I'd like to have a go at implementing this.

I'm obviously completely new to this codebase, so I'm gonna need a little guidance on

a. How the maintainers feel about the feature suggestion itself and the intended behaviour and
b. Roughly where I need to start to make these changes

Desired Behaviour

This is the behaviour of the new feature that I have in my head. It's basically a rip off of my very simple vim plugin https://github.com/benwainwright/fzf-project, which is fundamental to my workflow and I think everyone would benefit from. It would work like this:

  • A new key in the configuration file, called something like projects.workspaceRoots, which can take an array of strings representing a number of directories available on disk
  • A keyboard mapping that would open a quickfind search box very similar to the one opened when I press cmd-p
  • The data for this search box would be a list of all the first level directories contained within all of the "workspace roots" suggested above
  • so for example, if the key above was configured like this:
{
   "projects.workspaceRoots": [ "~/foo", "~/bar" ]
}
  • and my home directory tree looked like this:
- foo
|
|---- bish
|     |----- src
|     |----- docs
|
|---- bash
|.    |----- src
|.    |----- lib
|
- bar
|
|---- bosh
|      |----- src
|      |----- config
|
|---- bush
|.     |----- bin
  • then the data for the quickfind box would be the array ["bish", "bash", "bosh", "bush"]
  • selecting one of these options would then cause the application working directory to change to one of these folders

Next Steps

In order to implement this, I would need to (I'm guessing) know how to

  • Add to the main configuration file schema
  • Read the main configuration file
  • Create some kind of 'action' that is mappable by the user, and has a default mapping
  • Have the quick-find component display when this action executes
  • Search arbitrary folders on disk (I noticed you have bundled ripgrep - is there an API for that?)
  • Change the application working directory

Now this is probably going to take me some time, and I'm happy to do my own research. But if people have some time to give me some signposts to let me know what general areas of code I'm looking at to implement each of these bullet points, that would obviously speed me up.

@bryphe bryphe added A-workspace Area: Overall UX, editor layout, tabs/groups/splits etc. enhancement New feature or request labels Dec 12, 2020
@bryphe
Copy link
Member

bryphe commented Dec 12, 2020

Thanks for this proposal @benwainwright - I really appreciate the thought you put into it, and the way you broke down the steps.

Overall, I like the idea a lot. I'm jumping between different projects in different domains so I think I would use it too.

One feature that is in the back of my mind is multi-root workspaces - (#729 and described here: https://code.visualstudio.com/docs/editor/multi-root-workspaces). This is still a ways out; but I'm just considering how this proposal could integrate or if there would be a conflict. I actually think it could map well - each of those workspace roots described in projects.workspaceRoots is essentially a multi-workspace root.

The plan for implementation sounds good to me as well. Some thoughts on each bullet point:

Add to the main configuration file schema

The design we're moving towards is that the editor is subdivided into Features - and each feature can contribute configuration settings.

A good example of a feature-contributing-configuration is the auto-update feature:

module Configuration = {

We could add similar configuration settings to a feature - probably a good feature for this to live in would be the Feature_Workspace: https://github.com/onivim/oni2/blob/master/src/Feature/Workspace/Feature_Workspace.re

Once we have that configuration-contribution, we just need to wire it up here:

Feature_TitleBar.Contributions.configuration,
and then we'll be good to go to use it.

Create some kind of 'action' that is mappable by the user, and has a default mapping

Similar to the above - we have the concept of a 'command' contribution:

When the command is defined, it has a bindable action (in the one I linked - oni.app.checkForUpdates), and will show up in the command palette - Command+Shift+P.

The feature already has plumbing for commands, so it's really a matter of just adding it here and to the all array:

Have the quick-find component display when this action executes

The menu architecture needs to work (they currently aren't a feature - I'd like to have a Feature_Menu...) - but the code for them lives here: https://github.com/onivim/oni2/blob/master/src/Store/QuickmenuStoreConnector.re

This PR adds a few other things - but it adds a new menu for 'Open Buffers' picker (basically, the Cmd+P functionality when no workspace is opened): #2711 - might be a good reference point to see the places to change to add a picker.

Search arbitrary folders on disk (I noticed you have bundled ripgrep - is there an API for that?)

We do have a Ripgrep API, and we have a way to directly ask about the folders/files in a path - this

The subscriptions are one concept that isn't really part of React/Redux - they're inspired by Elm: https://guide.elm-lang.org/effects/

And the Ripgrep API lives here: https://github.com/onivim/oni2/blob/master/src/Core/Ripgrep.rei

Change the application working directory

Cool, we have this wired up in the Feature_Workspace already (for handling when the user picks a folder):

| FolderPicked(path) => (model, Effect(Effects.changeDirectory(path)))

Got pretty long, but let me know if you have any further questions. Thanks for the help!

@benwainwright
Copy link
Author

Thanks for the help!

Not a problem. As I'm just starting out in this domain, as I've already mentioned on other issues, I don't expect to be even close to finishing this for a long while. But I'll give it a shot!

@benwainwright
Copy link
Author

benwainwright commented Dec 12, 2020

@bryphe Okkkkk...., so I've forked the repo, and done what I think is the initial configuration wiring (master...benwainwright:master).

Now it gets a little less obvious to a newbie. Here is what I think need to do, tell me if I'm going along the right lines:

  • Add a new "command" (SelectWorkspace) to the variant defined here:

    type command =
    | CloseFolder
    | OpenFolder;

  • define(...) the command in the Commands submodule, making use of the variant I just created

  • Add a case to the switch in the same file (see below)

    switch (msg) {
    | FolderSelectionCanceled => (model, Nothing)
    | WorkingDirectoryChanged(workingDirectory) => (
    {
    workingDirectory,
    rootName: Filename.basename(workingDirectory),
    openedFolder: Some(workingDirectory),
    },
    WorkspaceChanged(Some(workingDirectory)),
    )
    | Command(CloseFolder) => (
    {...model, rootName: "", openedFolder: None},
    WorkspaceChanged(None),
    )
    | Command(OpenFolder) => (model, Effect(Effects.pickFolder))
    | FolderPicked(path) => (model, Effect(Effects.changeDirectory(path)))
    which matches against the new command

  • This then maps to a new binding in the Effect submodule in the same file (Effects.pickWorkspace...)

  • I'm thinking that Effects.pickWorkspace will be similar to changeDirectory, in that I'll do something, then dispatch to the store based on the results.

  • So there will be another call to IsoLinear.Effect.createWithDispatch. In the callback, I'll get the config that I previously wired up, use that with the ripgrep api that you referred me to in order to get the list of folders I need

  • I'll need to add a new variant to the quickMenuVariants here:

    and quickmenuVariant =

  • Then dispatch a QuickMenuShow(TheNewVariantIJustAdded) to the store along with the folder list payload

  • In the QuickmenuStoreConnector I can then handle that dispatch in order to show the menu

That should get me as far as showing the menu... I think? But now my back hurts, I've got stuff on tomorrow so I think its time to get an early night. If you could give me an indication of whether this looks like the right approach that would be fab.

@dfroger
Copy link

dfroger commented Jan 11, 2021

Hello,

Looks great. I have similar needs that I described in #2961.

My workflow is to use :NERDTreeFromBookmark command in (neo)vim. With this command I can choose a directory in a list of directories that I bookmarked (contains project root directories, as well as project sub directories that I frequently use). (I a perfect world, it would do a CTRL-P fuzzy-finding on this list of bookmarks)

When I select a directory, the file explorer opens and focus in this directory, and I can navigate to the files, or subdirectory/file that I want.

I create/delete the bookmarks directly from the file explorer with the :Bookmark command.

@bryphe
Copy link
Member

bryphe commented Jan 27, 2021

The functionality with the project-manager plugin in #3042 actually seems quite similar to this proposal - might be worth seeing if that extension can accomodate some of this use-case.

  • The proposed seems like the same functionality as the "projectManager.git.baseFolders" configuration exposed by that plugin
  • The quick-find lists the first-level directories of those roots with a command (ie, { "key": "<A-S-P>", "command": "projectManager.listProjects", "when": "normalMode"} as recommended by @iilonmasc in Plugin Problem with alefragnani.project-manager #3042)

The thing it's missing is the bookmark functionality mentioned above

@benwainwright
Copy link
Author

Oh wow, thanks @bryphe I'll have a look at that...

@benwainwright
Copy link
Author

@bryphe Sorry its been a while. Pandemic, y'know. Yes, I'm happy that the plugin you describe meets this use case so will close this issue.

... it doesn't work though, exactly as described on #3042

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-workspace Area: Overall UX, editor layout, tabs/groups/splits etc. enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants