Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Support opening multiple files at a time #823

Closed
wants to merge 1 commit into from

Conversation

conradz
Copy link
Contributor

@conradz conradz commented May 8, 2012

I changed the code the FILE_OPEN command so that the user can select multiple files to open at once, instead of having to open the files one at a time with a dialog prompting for each one. This had to change other parts of the code that used the FILE_OPEN command. I think I got all of the locations, but please review it 😃.

This probably needs pull request #121 on the brackets-app project that I created for supporting multiple file selection on the Windows app.

@mikechambers
Copy link
Contributor

Is this for mac and windows?

@conradz
Copy link
Contributor Author

conradz commented May 8, 2012

This uses the JavaScript interface for choosing files, so it should work on mac and windows when the brackets-app supports it. The pull request #121 in the brackets-app project fixes the multiple selection in the Windows app, but the JavaScript API for selecting multiple files has always existed in both the Windows and Mac version.

I can't test this pull request on a mac, but I think it should work. If you have any problems, let me know!

@njx
Copy link
Contributor

njx commented May 8, 2012

@redmunds will review since he's reviewing the brackets-app piece.

result.reject();
}

for (i = 0; i < files.length; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use Async.doSequentially() here. This code basically reimplements the Async.doInParallel() pattern, but since each individual doOpen() could show an error dialog we shouldn't run them all in parallel. This change should also make the code easier to read.

See saveAll() for an example of similar doSequentially() usage.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop has 2 other problems:

  1. doOpen() is only meant to open a single file because it automatically makes the file the current file, so this creates a race condition to see which of the multiple files is selected. Which is also unnecessary processing. Async.doSequentially fixes the race condition, but we still don't want to select every file in the list one at a time.
  2. For files inside the current project, they are not added to the working set, which defeats the purpose of opening multiple files. It looks like you only opened 1 file.

So, another code path is needed that opens files and adds them to working set, and then selects 1 file (first or last?). We don't want to update the existing code path because single-clicking a file in project tree should not add it top the working set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterflynn I can't figure out how to return the results when using Async.doSequentially. It seems that it just discards the results of the individual Deferreds. Is there any way to resolve the Deferred using the list of opened documents with Async.doSequentially? It does simplify the code nicely though.

@redmunds (regarding point 2) So are you saying that files that are opened from the open file dialog should always be added to the working set even if they are in the project? Is this the right function to do the opening multiple files in or what existing code path are you meaning?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@conradz The "another code path" I referred to needs to be written. It would be awesome if you want to take a stab at this.

I took a look at the code, and it doesn't seem too bad. I think we should add a selectFile parameter to doOpen(). All other calls should set it to true, and set it to false here. onOpen would need to be updated accordingly.

After each file is opened, then add each to the working set. Finally, select 1 of the files (not sure if it should be the first or the last in the list, so take your pick).

The code that adds file to working set if outside project in the select code should be moved, but I'm not sure where, so it's OK for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@conradz (on behalf of @peterflynn) Did you read the comment in utils/Async.js line 130? doOpen will show error dialogs for each file, so I think you just need the results from the master promise. I think you want to use failAndStopFast = false so that each file is attempted to be opened.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re doSequentially(): you can still attach listeners to each individual Deferred before returning it from beginProcessItem()... and then either push each doc onto a list as they get resolved, or add them at the right index if you want to keep the order the same. See the code around checkOneFile() DocumentManager for an example of the latter.

@redmunds
Copy link
Contributor

redmunds commented May 8, 2012

Conradz, this is functionality that we definitely wanted to add, so thanks for taking this on. Unfortunately, it surfaces a fundamental problem with File > Open not adding files (which are inside project) to the working folder. Please let us know if you need any help working out that part of the code.

@conradz
Copy link
Contributor Author

conradz commented May 9, 2012

Thanks for the feedback, I added some more replies/questions to the code review.

@ghost ghost assigned redmunds May 9, 2012
@@ -138,7 +138,7 @@ define(function (require, exports, module) {
* @return {!$.Promise}
*/
function addToWorkingSetAndSelect(fullPath) {
CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath});
CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, { files: [fullPath] });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing multiple files to this method doesn't seem right. While multiple files can be added to the working set, only a single file can be selected.

@peterflynn
Copy link
Member

Re all these issues around the working set... here's an alternative way we could do this that might be simpler for now:

  • When multiple files are selected in the dialog, call DocumentManager.addToWorkingSet() on all of them and then only call doOpen() on one of them. (Either the first or the last file in the array... which one do other apps seem to use?)
  • There's be no need to sort out all the Async stuff, since addToWorkingSet() runs synchronously and doOpen() would only be called once instead of N times.
  • We could then remove all the API changes if we wanted: _doOpenWithOptionalPath() could be left as something that only takes one file as an arg for now; the multi-file support could be specific to the case where the dialog is shown. This would make the diff much smaller and reduce the need for re-testing stuff.
  • The one subtlety with this is that we wouldn't actually load any of the other files until they become selected, similar to how working set entries act when the working set list has been restored from a previous launch. This would make the operation run faster, but it has the downside that if any of the files are unable to be read, the user won't get the error message until later when they try to select the file. That seems ok to me though (especially since the working set already behaves this way in the 'restored' case).

Opportunistically, we could still change doOpen() so it always adds to the working set. We feel like this is the right behavior anyway, but this change wouldn't be necessary for multi-file support if we implement it the way I suggested above.

@redmunds
Copy link
Contributor

redmunds commented May 9, 2012

Thanks, @peterflynn. I think that's a better approach.

@conradz
Copy link
Contributor Author

conradz commented May 10, 2012

Closing in favor of my new attempt, pull request #855. It uses the new approach @peterflynn suggested.

@conradz conradz closed this May 10, 2012
gideonthomas pushed a commit to gideonthomas/brackets that referenced this pull request Aug 31, 2017
…Url code hints (adobe#823)

* Using thirdparty-pathutils to remove deprecation warning

* Moved the PathUtils variable beside other module require statements
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants