Add (async) scope attribute collecting to DocumentController

This is for attr.project.XXX and attr.scm.XXX, although the latter is also provided by scm::info_t.

With this commit, the file::path_attributes function no longer collect this information.
This commit is contained in:
Allan Odgaard
2013-02-02 10:46:20 +01:00
parent 0d187e6694
commit 8c43974265
2 changed files with 71 additions and 89 deletions

View File

@@ -225,6 +225,7 @@ namespace
scm::ng::info_ptr _projectSCMInfo;
std::map<std::string, std::string> _projectSCMVariables;
std::vector<std::string> _projectScopeAttributes;
std::vector<std::string> _externalScopeAttributes;
scm::ng::info_ptr _documentSCMInfo;
std::map<std::string, std::string> _documentSCMVariables;
@@ -872,6 +873,73 @@ namespace
}
}
- (void)updateExternalAttributes
{
struct attribute_rule_t { std::string attribute; path::glob_t glob; std::string group; };
static attribute_rule_t const rules[] =
{
{ "attr.scm.svn", ".svn", "scm", },
{ "attr.scm.hg", ".hg", "scm", },
{ "attr.scm.git", ".git", "scm", },
{ "attr.scm.p4", ".p4config", "scm", },
{ "attr.project.ninja", "build.ninja", "build", },
{ "attr.project.make", "Makefile", "build", },
{ "attr.project.xcode", "*.xcodeproj", "build", },
{ "attr.project.rake", "Rakefile", "build", },
{ "attr.project.ant", "build.xml", "build", },
{ "attr.project.cmake", "CMakeLists.txt", "build", },
{ "attr.project.maven", "pom.xml", "build", },
{ "attr.project.scons", "SConstruct", "build", },
};
_externalScopeAttributes.clear();
if(!_documentPath && !_projectPath)
return;
std::string const projectDir = to_s(_projectPath ?: @"/");
std::string const documentDir = _documentPath ? to_s(_documentPath) : path::join(projectDir, "dummy");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
std::vector<std::string> res;
std::set<std::string> groups;
std::string dir = documentDir;
do {
dir = path::parent(dir);
auto entries = path::entries(dir);
for(auto rule : rules)
{
if(groups.find(rule.group) != groups.end())
continue;
for(auto entry : entries)
{
if(rule.glob.does_match(entry->d_name))
{
res.push_back(rule.attribute);
if(rule.group != NULL_STR)
{
groups.insert(rule.group);
break;
}
}
}
}
} while(dir != projectDir);
dispatch_async(dispatch_get_main_queue(), ^{
std::string const currentProjectDir = to_s(_projectPath ?: @"/");
std::string const currentDocumentDir = _documentPath ? to_s(_documentPath) : path::join(projectDir, "dummy");
if(projectDir == currentProjectDir && documentDir == currentDocumentDir)
_externalScopeAttributes = res;
});
});
}
- (void)setProjectPath:(NSString*)newProjectPath
{
if(_projectPath != newProjectPath && ![_projectPath isEqualToString:newProjectPath])
@@ -900,6 +968,7 @@ namespace
if(customAttributes != NULL_STR)
_projectScopeAttributes.push_back(customAttributes);
[self updateExternalAttributes];
[self updateWindowTitle];
}
}
@@ -956,6 +1025,7 @@ namespace
self.documentSCMVariables = std::map<std::string, std::string>();
}
[self updateExternalAttributes];
[self updateProxyIcon];
[self updateWindowTitle];
}
@@ -1046,6 +1116,7 @@ namespace
attributes.insert(_documentScopeAttributes.begin(), _documentScopeAttributes.end());
attributes.insert(_projectScopeAttributes.begin(), _projectScopeAttributes.end());
attributes.insert(_externalScopeAttributes.begin(), _externalScopeAttributes.end());
return [NSString stringWithCxxString:text::join(attributes, " ")];
}

View File

@@ -7,93 +7,6 @@
#include <text/tokenize.h>
#include <oak/oak.h>
namespace
{
struct attribute_rule_t
{
attribute_rule_t (std::string const& attribute, path::glob_t const& glob, std::string const& group) : attribute(attribute), glob(glob), group(group) { }
std::string attribute;
path::glob_t glob;
std::string group;
};
template <typename _OutputIter>
_OutputIter parse_rules (plist::any_t const& plist, _OutputIter out)
{
plist::array_t rules;
if(plist::get_key_path(plist, "rules", rules))
{
iterate(dict, rules)
{
std::string attr, glob, group = NULL_STR;
if(plist::get_key_path(*dict, "attribute", attr) && plist::get_key_path(*dict, "glob", glob))
{
plist::get_key_path(*dict, "group", group);
*out++ = attribute_rule_t(attr, glob, group);
}
}
}
return out;
}
static std::vector<attribute_rule_t> attribute_specifiers ()
{
static std::string const DefaultScopeAttributes =
"{ rules = ("
" { attribute = 'attr.scm.svn'; glob = '.svn'; group = 'scm'; },"
" { attribute = 'attr.scm.hg'; glob = '.hg'; group = 'scm'; },"
" { attribute = 'attr.scm.git'; glob = '.git'; group = 'scm'; },"
" { attribute = 'attr.scm.p4'; glob = '.p4config'; group = 'scm'; },"
" { attribute = 'attr.project.ninja'; glob = 'build.ninja'; group = 'build'; },"
" { attribute = 'attr.project.make'; glob = 'Makefile'; group = 'build'; },"
" { attribute = 'attr.project.xcode'; glob = '*.xcodeproj'; group = 'build'; },"
" { attribute = 'attr.project.rake'; glob = 'Rakefile'; group = 'build'; },"
" { attribute = 'attr.project.ant'; glob = 'build.xml'; group = 'build'; },"
" { attribute = 'attr.project.cmake'; glob = 'CMakeLists.txt'; group = 'build'; },"
" { attribute = 'attr.project.maven'; glob = 'pom.xml'; group = 'build'; },"
" { attribute = 'attr.project.scons'; glob = 'SConstruct'; group = 'build'; },"
"); }";
std::vector<attribute_rule_t> res;
parse_rules(plist::load(path::join(path::home(), "Library/Application Support/TextMate/ScopeAttributes.plist")), back_inserter(res));
parse_rules(plist::parse_ascii(DefaultScopeAttributes), back_inserter(res));
return res;
}
static void directory_attributes (std::string const& dir, std::vector<std::string>& res)
{
if(dir == NULL_STR || dir == "" || dir[0] != '/')
return;
std::set<std::string> groups;
for(std::string cwd = dir; cwd != "/"; cwd = path::parent(cwd))
{
auto entries = path::entries(cwd);
static std::vector<attribute_rule_t> const specifiers = attribute_specifiers();
iterate(specifier, specifiers)
{
if(groups.find(specifier->group) != groups.end())
continue;
iterate(entry, entries)
{
if(specifier->glob.does_match((*entry)->d_name))
{
res.push_back(specifier->attribute);
if(specifier->group != NULL_STR)
{
groups.insert(specifier->group);
break;
}
}
}
}
}
}
}
namespace file
{
std::string path_attributes (std::string const& path, std::string const& dir)
@@ -130,8 +43,6 @@ namespace file
res.push_back(text::format("attr.os-version.%zd.%zd.%zd", (ssize_t)major, (ssize_t)minor, (ssize_t)bugFix));
std::string const parentDir = dir == NULL_STR ? path::parent(path) : dir;
directory_attributes(parentDir, res);
res.push_back(settings_for_path(path, text::join(res, " "), parentDir).get(kSettingsScopeAttributesKey, ""));
res.erase(std::remove(res.begin(), res.end(), ""), res.end());
return text::join(res, " ");