diff options
Diffstat (limited to '')
-rw-r--r-- | src/base/attr_line.hh | 300 |
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()) { |