summaryrefslogtreecommitdiffstats
path: root/src/base/attr_line.hh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/base/attr_line.hh300
1 files changed, 65 insertions, 235 deletions
diff --git a/src/base/attr_line.hh b/src/base/attr_line.hh
index c9cb6a8..c294321 100644
--- a/src/base/attr_line.hh
+++ b/src/base/attr_line.hh
@@ -40,130 +40,10 @@
#include "fmt/format.h"
#include "intern_string.hh"
+#include "line_range.hh"
#include "string_attr_type.hh"
#include "string_util.hh"
-/**
- * Encapsulates a range in a string.
- */
-struct line_range {
- enum class unit {
- bytes,
- codepoint,
- };
-
- int lr_start;
- int lr_end;
- unit lr_unit;
-
- explicit line_range(int start = -1, int end = -1, unit u = unit::bytes)
- : lr_start(start), lr_end(end), lr_unit(u)
- {
- }
-
- bool is_valid() const { return this->lr_start != -1; }
-
- int length() const
- {
- return this->lr_end == -1 ? INT_MAX : this->lr_end - this->lr_start;
- }
-
- bool empty() const { return this->length() == 0; }
-
- void clear()
- {
- this->lr_start = -1;
- this->lr_end = -1;
- }
-
- int end_for_string(const std::string& str) const
- {
- return this->lr_end == -1 ? str.length() : this->lr_end;
- }
-
- bool contains(int pos) const
- {
- return this->lr_start <= pos
- && (this->lr_end == -1 || pos < this->lr_end);
- }
-
- bool contains(const struct line_range& other) const
- {
- return this->contains(other.lr_start)
- && (this->lr_end == -1 || other.lr_end <= this->lr_end);
- }
-
- bool intersects(const struct line_range& other) const
- {
- if (this->contains(other.lr_start)) {
- return true;
- }
- if (other.lr_end > 0 && this->contains(other.lr_end - 1)) {
- return true;
- }
- if (other.contains(this->lr_start)) {
- return true;
- }
-
- return false;
- }
-
- line_range intersection(const struct line_range& other) const;
-
- line_range& shift(int32_t start, int32_t amount);
-
- void ltrim(const char* str)
- {
- while (this->lr_start < this->lr_end && isspace(str[this->lr_start])) {
- this->lr_start += 1;
- }
- }
-
- bool operator<(const struct line_range& rhs) const
- {
- if (this->lr_start < rhs.lr_start) {
- return true;
- }
- if (this->lr_start > rhs.lr_start) {
- return false;
- }
-
- // this->lr_start == rhs.lr_start
- if (this->lr_end == rhs.lr_end) {
- return false;
- }
-
- if (this->lr_end < rhs.lr_end) {
- return false;
- }
- return true;
- }
-
- bool operator==(const struct line_range& rhs) const
- {
- return (this->lr_start == rhs.lr_start && this->lr_end == rhs.lr_end);
- }
-
- const char* substr(const std::string& str) const
- {
- if (this->lr_start == -1) {
- return str.c_str();
- }
- return &(str.c_str()[this->lr_start]);
- }
-
- size_t sublen(const std::string& str) const
- {
- if (this->lr_start == -1) {
- return str.length();
- }
- if (this->lr_end == -1) {
- return str.length() - this->lr_start;
- }
- return this->length();
- }
-};
-
inline line_range
to_line_range(const string_fragment& frag)
{
@@ -214,35 +94,11 @@ struct string_attr_wrapper {
/** A map of line ranges to attributes for that range. */
using string_attrs_t = std::vector<string_attr>;
-inline string_attrs_t::const_iterator
-find_string_attr(const string_attrs_t& sa,
- const string_attr_type_base* type,
- int start = 0)
-{
- string_attrs_t::const_iterator iter;
-
- for (iter = sa.begin(); iter != sa.end(); ++iter) {
- if (iter->sa_type == type && iter->sa_range.lr_start >= start) {
- break;
- }
- }
-
- return iter;
-}
-
-inline nonstd::optional<const string_attr*>
-get_string_attr(const string_attrs_t& sa,
- const string_attr_type_base* type,
- int start = 0)
-{
- auto iter = find_string_attr(sa, type, start);
-
- if (iter == sa.end()) {
- return nonstd::nullopt;
- }
+string_attrs_t::const_iterator find_string_attr(
+ const string_attrs_t& sa, const string_attr_type_base* type, int start = 0);
- return nonstd::make_optional(&(*iter));
-}
+nonstd::optional<const string_attr*> get_string_attr(
+ const string_attrs_t& sa, const string_attr_type_base* type, int start = 0);
template<typename T>
inline nonstd::optional<string_attr_wrapper<T>>
@@ -276,42 +132,11 @@ find_string_attr_containing(const string_attrs_t& sa,
return iter;
}
-inline string_attrs_t::iterator
-find_string_attr(string_attrs_t& sa, const struct line_range& lr)
-{
- string_attrs_t::iterator iter;
-
- for (iter = sa.begin(); iter != sa.end(); ++iter) {
- if (lr.contains(iter->sa_range)) {
- break;
- }
- }
-
- return iter;
-}
-
-inline string_attrs_t::const_iterator
-find_string_attr(const string_attrs_t& sa, size_t near)
-{
- auto nearest = sa.end();
- ssize_t last_diff = INT_MAX;
-
- for (auto iter = sa.begin(); iter != sa.end(); ++iter) {
- const auto& lr = iter->sa_range;
-
- if (!lr.is_valid() || !lr.contains(near)) {
- continue;
- }
-
- ssize_t diff = near - lr.lr_start;
- if (diff < last_diff) {
- last_diff = diff;
- nearest = iter;
- }
- }
+string_attrs_t::iterator find_string_attr(string_attrs_t& sa,
+ const struct line_range& lr);
- return nearest;
-}
+string_attrs_t::const_iterator find_string_attr(const string_attrs_t& sa,
+ size_t near);
template<typename T>
inline string_attrs_t::const_iterator
@@ -341,47 +166,18 @@ rfind_string_attr_if(const string_attrs_t& sa, ssize_t near, T predicate)
return nearest;
}
-inline struct line_range
-find_string_attr_range(const string_attrs_t& sa, string_attr_type_base* type)
-{
- auto iter = find_string_attr(sa, type);
+struct line_range find_string_attr_range(const string_attrs_t& sa,
+ string_attr_type_base* type);
- if (iter != sa.end()) {
- return iter->sa_range;
- }
+void remove_string_attr(string_attrs_t& sa, const struct line_range& lr);
- return line_range();
-}
+void remove_string_attr(string_attrs_t& sa, string_attr_type_base* type);
-inline void
-remove_string_attr(string_attrs_t& sa, const struct line_range& lr)
-{
- string_attrs_t::iterator iter;
-
- while ((iter = find_string_attr(sa, lr)) != sa.end()) {
- sa.erase(iter);
- }
-}
+void shift_string_attrs(string_attrs_t& sa, int32_t start, int32_t amount);
-inline void
-remove_string_attr(string_attrs_t& sa, string_attr_type_base* type)
-{
- for (auto iter = sa.begin(); iter != sa.end();) {
- if (iter->sa_type == type) {
- iter = sa.erase(iter);
- } else {
- ++iter;
- }
- }
-}
-
-inline void
-shift_string_attrs(string_attrs_t& sa, int32_t start, int32_t amount)
-{
- for (auto& iter : sa) {
- iter.sa_range.shift(start, amount);
- }
-}
+void shift_string_attrs(string_attrs_t& sa,
+ const line_range& cover,
+ int32_t amount);
struct text_wrap_settings {
text_wrap_settings& with_indent(int indent)
@@ -425,6 +221,13 @@ public:
return retval.with_ansi_string("%s", str);
}
+ static inline attr_line_t from_ansi_str(const std::string& str)
+ {
+ attr_line_t retval;
+
+ return retval.with_ansi_string(str);
+ }
+
/** @return The string itself. */
std::string& get_string() { return this->al_string; }
@@ -517,15 +320,6 @@ public:
return *this;
}
- attr_line_t& append_quoted(const attr_line_t& al)
- {
- this->al_string.append("\u201c");
- this->append(al);
- this->al_string.append("\u201d");
-
- return *this;
- }
-
template<typename S>
attr_line_t& append_quoted(S s)
{
@@ -548,18 +342,31 @@ public:
return *this;
}
- template<typename S>
- attr_line_t& append(S str)
+ attr_line_t& append(const std::string& str)
{
this->al_string.append(str);
return *this;
}
+ attr_line_t& append(const char* str)
+ {
+ this->al_string.append(str);
+ return *this;
+ }
+
+ template<typename V>
+ attr_line_t& append(const V& v)
+ {
+ this->al_string.append(fmt::to_string(v));
+ return *this;
+ }
+
template<typename... Args>
attr_line_t& appendf(fmt::format_string<Args...> fstr, Args&&... args)
{
- this->template append(
- fmt::vformat(fstr, fmt::make_format_args(args...)));
+ fmt::vformat_to(std::back_inserter(this->al_string),
+ fstr,
+ fmt::make_format_args(args...));
return *this;
}
@@ -635,6 +442,24 @@ public:
return *this;
}
+ template<typename S>
+ attr_line_t& insert(size_t index,
+ const std::pair<S, string_attr_pair>& value)
+ {
+ size_t start_len = this->al_string.length();
+
+ this->insert(index, std::move(value.first));
+
+ line_range lr{
+ (int) index,
+ (int) (index + (this->al_string.length() - start_len)),
+ };
+
+ this->al_attrs.emplace_back(lr, value.second);
+
+ return *this;
+ }
+
template<typename... Args>
attr_line_t& add_header(Args... args)
{
@@ -657,7 +482,7 @@ public:
attr_line_t& erase(size_t pos, size_t len = std::string::npos);
- attr_line_t& rtrim();
+ attr_line_t& rtrim(nonstd::optional<const char*> chars = nonstd::nullopt);
attr_line_t& erase_utf8_chars(size_t start)
{
@@ -695,6 +520,11 @@ public:
return utf8_string_length(this->al_string).unwrapOr(this->length());
}
+ size_t column_width() const
+ {
+ return string_fragment::from_str(this->al_string).column_width();
+ }
+
std::string get_substring(const line_range& lr) const
{
if (!lr.is_valid()) {