Merge branch 'master' into config

This commit is contained in:
Nathan Sobo
2012-12-12 16:48:58 -08:00
10 changed files with 124 additions and 55 deletions

View File

@@ -16,6 +16,9 @@ var $native = {};
native function traverseTree(path, onFile, onDirectory);
$native.traverseTree = traverseTree;
native function getAllPathsAsync(path);
$native.getAllPathsAsync = getAllPathsAsync;
native function isFile(path);
$native.isFile = isFile;

View File

@@ -103,6 +103,58 @@ bool Native::Execute(const CefString& name,
return true;
}
else if (name == "getAllPathsAsync") {
std::string argument = arguments[0]->GetStringValue().ToString();
CefRefPtr<CefV8Value> callback = arguments[1];
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
int rootPathLength = argument.size() + 1;
char rootPath[rootPathLength];
strcpy(rootPath, argument.c_str());
char * const treePaths[] = {rootPath, NULL};
FTS *tree = fts_open(treePaths, FTS_COMFOLLOW | FTS_PHYSICAL| FTS_NOCHDIR | FTS_NOSTAT, NULL);
std::vector<std::string> paths;
if (tree != NULL) {
FTSENT *entry;
int arrayIndex = 0;
while ((entry = fts_read(tree)) != NULL) {
if (entry->fts_level == 0) {
continue;
}
bool isFile = entry->fts_info == FTS_NSOK;
bool isDir = entry->fts_info == FTS_D;
if (!isFile && !isDir) {
continue;
}
int pathLength = entry->fts_pathlen - rootPathLength;
char relative[pathLength + 1];
relative[pathLength] = '\0';
strncpy(relative, entry->fts_path + rootPathLength, pathLength);
paths.push_back(relative);
}
}
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
context->Enter();
CefRefPtr<CefV8Value> v8Paths = CefV8Value::CreateArray(paths.size());
for (int i = 0; i < paths.size(); i++) {
v8Paths->SetValue(i, CefV8Value::CreateString(paths[i]));
}
CefV8ValueList callbackArgs;
callbackArgs.push_back(v8Paths);
callback->ExecuteFunction(callback, callbackArgs);
context->Exit();
});
});
return true;
}
else if (name == "traverseTree") {
std::string argument = arguments[0]->GetStringValue().ToString();
int rootPathLength = argument.size() + 1;

View File

@@ -110,19 +110,34 @@ describe "Project", ->
expect(project.getRootDirectory()?).toBeFalsy()
describe ".getFilePaths()", ->
it "ignores files that return true from atom.ignorePath(path)", ->
spyOn(project, 'ignoreDirectory').andCallFake (path) -> fs.base(path).match /a$/
spyOn(project, 'ignoreFile').andCallFake (path) -> fs.base(path).match /a$/
it "asynchronously returns file paths using a promise", ->
paths = null
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
paths = project.getFilePaths()
expect(paths).not.toContain('a')
expect(paths).toContain('b')
runs ->
expect(paths.length).toBeGreaterThan 0
it "ignores files that return true from atom.ignorePath(path)", ->
spyOn(project, 'isPathIgnored').andCallFake (path) -> fs.base(path).match /a$/
paths = null
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
runs ->
expect(paths).not.toContain('a')
expect(paths).toContain('b')
it "ignores files in gitignore for projects in a git tree", ->
project.setHideIgnoredFiles(true)
project.setPath(require.resolve('fixtures/git/working-dir'))
paths = project.getFilePaths()
expect(paths).not.toContain('ignored.txt')
paths = null
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
runs ->
expect(paths).not.toContain('ignored.txt')
describe ".scan(options, callback)", ->
describe "when called with a regex", ->

View File

@@ -598,7 +598,7 @@ class Editor extends View
if @activeEditSession.getSoftWrap()
@addClass 'soft-wrap'
@_setSoftWrapColumn = => @setSoftWrapColumn()
$(window).on 'resize', @_setSoftWrapColumn
$(window).on "resize.editor#{@id}", @_setSoftWrapColumn
else
@removeClass 'soft-wrap'
$(window).off 'resize', @_setSoftWrapColumn

View File

@@ -24,13 +24,10 @@ class Project
@setPath(path)
@editSessions = []
@buffers = []
@ignoredFolderNames = [
@ignoredNames = [
'.git'
]
@ignoredFileNames = [
'.DS_Store'
]
@ignoredPathRegexes = []
@repo = new Git(path)
destroy: ->
@@ -55,52 +52,27 @@ class Project
@rootDirectory
getFilePaths: ->
filePaths = []
deferred = $.Deferred()
fs.getAllPathsAsync @getPath(), (paths) =>
paths = paths.filter (path) => not @isPathIgnored(path)
deferred.resolve(paths)
deferred.promise()
onFile = (path) =>
filePaths.push(path) unless @ignoreFile(path)
onDirectory = (path) =>
return not @ignoreDirectory(path)
fs.traverseTree @getPath(), onFile, onDirectory
filePaths
ignoreDirectory: (path) ->
isPathIgnored: (path) ->
lastSlash = path.lastIndexOf('/')
if lastSlash isnt -1
name = path.substring(lastSlash + 1)
else
name = path
for ignored in @ignoredFolderNames
for ignored in @ignoredNames
return true if name is ignored
for regex in @ignoredPathRegexes
return true if path.match(regex)
@ignoreRepositoryPath(path)
ignoreFile: (path) ->
lastSlash = path.lastIndexOf('/')
if lastSlash isnt -1
name = path.substring(lastSlash + 1)
else
name = path
for ignored in @ignoredFileNames
return true if name is ignored
for regex in @ignoredPathRegexes
return true if path.match(regex)
@ignoreRepositoryPath(path)
ignoreRepositoryPath: (path) ->
@hideIgnoredFiles and @repo.isPathIgnored(fs.join(@getPath(), path))
ignorePathRegex: ->
@ignoredPathRegexes.map((regex) -> "(#{regex.source})").join("|")
resolve: (filePath) ->
filePath = fs.join(@getPath(), filePath) unless filePath[0] == '/'
fs.absolute filePath

View File

@@ -9,6 +9,7 @@ class SelectList extends View
@div class: @viewClass(), =>
@subview 'miniEditor', new Editor(mini: true)
@div class: 'error', outlet: 'error'
@div class: 'loading', outlet: 'loading'
@ol outlet: 'list'
@viewClass: -> 'select-list'
@@ -38,6 +39,7 @@ class SelectList extends View
setArray: (@array) ->
@populateList()
@selectItem(@list.find('li:first'))
@setLoading()
setError: (message) ->
if not message or message.length == ""
@@ -49,6 +51,13 @@ class SelectList extends View
@error.show()
@addClass("error")
setLoading: (message) ->
if not message or message.length == ""
@loading.text("").hide()
else
@setError()
@loading.text(message).show()
populateList: ->
filterQuery = @miniEditor.getText()
if filterQuery.length

View File

@@ -18,7 +18,7 @@ describe 'FuzzyFinder', ->
describe "file-finder behavior", ->
describe "toggling", ->
describe "when the root view's project has a path", ->
it "shows the FuzzyFinder or hides it and returns focus to the active editor if it already showing", ->
it "shows the FuzzyFinder or hides it nad returns focus to the active editor if it already showing", ->
rootView.attachToDom()
expect(rootView.find('.fuzzy-finder')).not.toExist()
rootView.find('.editor').trigger 'editor:split-right'
@@ -40,13 +40,25 @@ describe 'FuzzyFinder', ->
expect(finder.miniEditor.getText()).toBe ''
it "shows all relative file paths for the current project and selects the first", ->
rootView.attachToDom()
finder.maxItems = Infinity
rootView.trigger 'fuzzy-finder:toggle-file-finder'
paths = rootView.project.getFilePaths()
expect(finder.list.children('li').length).toBe paths.length, finder.maxResults
for path in paths
expect(finder.list.find("li:contains(#{path})")).toExist()
expect(finder.list.children().first()).toHaveClass 'selected'
paths = null
expect(finder.find(".loading")).toBeVisible()
expect(finder.find(".loading")).toHaveText "Indexing..."
waitsForPromise ->
rootView.project.getFilePaths().done (foundPaths) -> paths = foundPaths
waitsFor ->
finder.list.children('li').length > 0
runs ->
expect(finder.list.children('li').length).toBe paths.length, finder.maxResults
for path in paths
expect(finder.list.find("li:contains(#{path})")).toExist()
expect(finder.list.children().first()).toHaveClass 'selected'
expect(finder.find(".loading")).not.toBeVisible()
describe "when root view's project has no path", ->
beforeEach ->

View File

@@ -51,7 +51,9 @@ class FuzzyFinder extends SelectList
@attach() if @paths?.length
populateProjectPaths: ->
@setArray(@rootView.project.getFilePaths())
@setLoading("Indexing...")
@rootView.project.getFilePaths().done (paths) =>
@setArray(paths)
populateOpenBufferPaths: ->
@paths = @rootView.getOpenBufferPaths().map (path) =>

View File

@@ -17,10 +17,11 @@ class DirectoryView extends View
header: null
project: null
initialize: ({@directory, isExpanded, @project} = {}) ->
initialize: ({@directory, isExpanded, @project, parent} = {}) ->
@expand() if isExpanded
@disclosureArrow.on 'click', => @toggleExpansion()
@directoryName.addClass('ignored') if new Git(@directory.getPath()).isPathIgnored(@directory.getPath())
repositoryPath = parent?.getPath() or @directory.getPath()
@directoryName.addClass('ignored') if new Git(repositoryPath).isPathIgnored(@directory.getPath())
getPath: ->
@directory.path
@@ -35,7 +36,7 @@ class DirectoryView extends View
for entry in @directory.getEntries()
continue if @isPathIgnored(entry.path)
if entry instanceof Directory
@entries.append(new DirectoryView(directory: entry, isExpanded: false, project: @project))
@entries.append(new DirectoryView(directory: entry, isExpanded: false, project: @project, parent: @directory))
else
@entries.append(new FileView(entry))
@append(@entries)

View File

@@ -112,6 +112,9 @@ module.exports =
@makeTree(@directory(path))
@makeDirectory(path)
getAllPathsAsync: (rootPath, callback) ->
$native.getAllPathsAsync(rootPath, callback)
traverseTree: (rootPath, onFile, onDirectory) ->
$native.traverseTree(rootPath, onFile, onDirectory)