mirror of
https://github.com/textmate/textmate.git
synced 2026-04-28 03:00:34 -04:00
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:
@@ -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, " ")];
|
||||
}
|
||||
|
||||
@@ -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, " ");
|
||||
|
||||
Reference in New Issue
Block a user