Files
textmate/Frameworks/scope/src/scope.cc
2012-08-28 20:10:55 +02:00

149 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "scope.h"
#include "parse.h"
#include <text/format.h>
#include <oak/oak.h>
namespace scope
{
scope_t wildcard("x-any");
// =========
// = Scope =
// =========
scope_t::scope_t () { ; }
scope_t::scope_t (char const* scope) { setup(scope); }
scope_t::scope_t (std::string const& scope) { setup(scope); }
void scope_t::setup (std::string const& scope)
{
path.reset(new scope::types::path_t);
scope::parse::path(scope.data(), scope.data() + scope.size(), *path);
}
bool scope_t::has_prefix (scope_t const& rhs) const
{
std::vector<types::scope_t> const& lhsScopes = path ? path->scopes : std::vector<types::scope_t>();
std::vector<types::scope_t> const& rhsScopes = rhs.path ? rhs.path->scopes : std::vector<types::scope_t>();
size_t i = 0;
for(; i < std::min(lhsScopes.size(), rhsScopes.size()); ++i)
{
if(lhsScopes[i] != rhsScopes[i])
break;
}
return i == rhsScopes.size();
}
scope_t scope_t::append (std::string const& atom) const
{
scope_t res;
res.path.reset(new types::path_t(path ? *path : types::path_t()));
types::scope_t scope;
parse::scope(atom.data(), atom.data() + atom.size(), scope);
res.path->scopes.push_back(scope);
return res;
}
scope_t scope_t::parent () const
{
scope_t res;
if(path && !path->scopes.empty())
{
res.path.reset(new types::path_t(*path));
res.path->scopes.pop_back();
}
return res;
}
bool scope_t::operator== (scope_t const& rhs) const { return (!path && !rhs.path) || (path && rhs.path && *path == *rhs.path); }
bool scope_t::operator!= (scope_t const& rhs) const { return !(*this == rhs); }
bool scope_t::operator< (scope_t const& rhs) const { return (!path && rhs.path) || (path && rhs.path && *path < *rhs.path); }
scope_t::operator bool () const { return path ? true : false; }
scope_t shared_prefix (scope_t const& lhs, scope_t const& rhs)
{
std::vector<types::scope_t> const& lhsScopes = lhs.path ? lhs.path->scopes : std::vector<types::scope_t>();
std::vector<types::scope_t> const& rhsScopes = rhs.path ? rhs.path->scopes : std::vector<types::scope_t>();
size_t i = 0;
for(; i < std::min(lhsScopes.size(), rhsScopes.size()); ++i)
{
if(lhsScopes[i] != rhsScopes[i])
break;
}
scope_t res;
res.path.reset(new types::path_t);
res.path->scopes.insert(res.path->scopes.end(), lhsScopes.begin(), lhsScopes.begin() + i);
return res;
}
std::string xml_difference (scope_t const& lhs, scope_t const& rhs, std::string const& open, std::string const& close)
{
std::vector<types::scope_t> const& lhsScopes = lhs.path ? lhs.path->scopes : std::vector<types::scope_t>();
std::vector<types::scope_t> const& rhsScopes = rhs.path ? rhs.path->scopes : std::vector<types::scope_t>();
size_t i = 0;
for(; i < std::min(lhsScopes.size(), rhsScopes.size()); ++i)
{
if(lhsScopes[i] != rhsScopes[i])
break;
}
std::string res = "";
for(size_t j = lhsScopes.size(); j > i; --j)
res += open + "/" + to_s(lhsScopes[j-1]) + close;
for(size_t j = i; j < rhsScopes.size(); ++j)
res += open + to_s(rhsScopes[j]) + close;
return res;
}
std::string to_s (scope_t const& s)
{
return s.path ? to_s(*s.path) : "";
}
std::string to_s (context_t const& c)
{
return c.left == c.right ? text::format("(l/r %s)", to_s(c.left).c_str()) : text::format("(left %s, right %s)", to_s(c.left).c_str(), to_s(c.right).c_str());
}
// ============
// = Selector =
// ============
selector_t::selector_t () { ; }
selector_t::selector_t (char const* str) { setup(str); }
selector_t::selector_t (std::string const& str) { setup(str); }
void selector_t::setup (std::string const& str)
{
selector.reset(new scope::types::selector_t);
scope::parse::selector(str.data(), str.data() + str.size(), *selector);
}
std::string to_s (selector_t const& s)
{
return s.selector ? to_s(*s.selector) : "";
}
// ============
// = Matching =
// ============
bool selector_t::does_match (context_t const& scope, double* rank) const
{
if(!selector)
{
if(rank)
*rank = 0;
return true;
}
if(!scope.left.path || !scope.right.path)
return false;
return scope.left == wildcard || scope.right == wildcard || selector->does_match(*scope.left.path, *scope.right.path, rank);
}
}