mirror of
https://github.com/textmate/textmate.git
synced 2026-01-22 21:27:56 -05:00
149 lines
4.3 KiB
C++
149 lines
4.3 KiB
C++
#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);
|
||
}
|
||
}
|