Fcitx
text.cpp
1 /*
2  * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 
8 #include "text.h"
9 #include <algorithm>
10 #include <cstddef>
11 #include <iterator>
12 #include <memory>
13 #include <ostream>
14 #include <string>
15 #include <tuple>
16 #include <utility>
17 #include <vector>
18 #include "fcitx-utils/macros.h"
21 #include "fcitx-utils/utf8.h"
22 
23 namespace fcitx {
24 
25 class TextPrivate {
26 public:
27  TextPrivate() = default;
28  FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_COPY(TextPrivate)
29 
30  std::vector<std::tuple<std::string, TextFormatFlags>> texts_;
31  int cursor_ = -1;
32 };
33 
34 Text::Text() : d_ptr(std::make_unique<TextPrivate>()) {}
35 
36 Text::Text(std::string text, TextFormatFlags flag) : Text() {
37  append(std::move(text), flag);
38 }
39 
40 FCITX_DEFINE_DPTR_COPY_AND_DEFAULT_DTOR_AND_MOVE(Text)
41 
42 void Text::clear() {
43  FCITX_D();
44  d->texts_.clear();
45  setCursor();
46 }
47 
48 int Text::cursor() const {
49  FCITX_D();
50  return d->cursor_;
51 }
52 
53 void Text::setCursor(int pos) {
54  FCITX_D();
55  d->cursor_ = pos;
56 }
57 
58 void Text::append(std::string str, TextFormatFlags flag) {
59  FCITX_D();
61  d->texts_.emplace_back(std::move(str), flag);
62 }
63 
64 void Text::append(Text text) {
65  FCITX_D();
66  std::copy(std::make_move_iterator(text.d_ptr->texts_.begin()),
67  std::make_move_iterator(text.d_ptr->texts_.end()),
68  std::back_inserter(d->texts_));
69 }
70 
71 const std::string &Text::stringAt(int idx) const {
72  FCITX_D();
73  return std::get<std::string>(d->texts_[idx]);
74 }
75 
76 TextFormatFlags Text::formatAt(int idx) const {
77  FCITX_D();
78  return std::get<TextFormatFlags>(d->texts_[idx]);
79 }
80 
81 size_t Text::size() const {
82  FCITX_D();
83  return d->texts_.size();
84 }
85 
86 bool Text::empty() const {
87  FCITX_D();
88  return d->texts_.empty();
89 }
90 
91 std::string Text::toString() const {
92  FCITX_D();
93  std::string result;
94  for (const auto &p : d->texts_) {
95  result += std::get<std::string>(p);
96  }
97 
98  return result;
99 }
100 
101 size_t Text::textLength() const {
102  FCITX_D();
103  size_t length = 0;
104  for (const auto &p : d->texts_) {
105  length += std::get<std::string>(p).size();
106  }
107 
108  return length;
109 }
110 
111 std::string Text::toStringForCommit() const {
112  FCITX_D();
113  std::string result;
114  for (const auto &p : d->texts_) {
115  if (!(std::get<TextFormatFlags>(p) & TextFormatFlag::DontCommit)) {
116  result += std::get<std::string>(p);
117  }
118  }
119 
120  return result;
121 }
122 
123 std::ostream &operator<<(std::ostream &os, const Text &text) {
124  os << "Text(";
125  for (size_t i = 0; i < text.size(); i++) {
126  os << "<" << text.stringAt(i) << ", flag=" << text.formatAt(i) << ">";
127  if (i + 1 != text.size()) {
128  os << ", ";
129  }
130  }
131  os << ", cursor=" << text.cursor() << ")";
132  return os;
133 }
134 
135 std::vector<Text> Text::splitByLine() const {
136  FCITX_D();
137  std::vector<Text> texts;
138  // Put first line.
139  texts.emplace_back();
140  for (const auto &p : d->texts_) {
141  if (std::get<std::string>(p).empty()) {
142  continue;
143  }
144  auto lines = stringutils::split(std::get<std::string>(p), "\n",
145  stringutils::SplitBehavior::KeepEmpty);
146  auto flag = std::get<TextFormatFlags>(p);
147  texts.back().append(lines[0], flag);
148  for (size_t i = 1; i < lines.size(); i++) {
149  texts.emplace_back();
150  texts.back().append(lines[i], flag);
151  }
152  }
153 
154  return texts;
155 }
156 
158  FCITX_D();
159 
160  Text normalized;
161  std::string curStr;
162  TextFormatFlags curFormat;
163  for (const auto &[str, format] : d->texts_) {
164  if (str.empty()) {
165  continue;
166  }
167  if (curFormat == format) {
168  curStr.append(str);
169  } else {
170  if (!curStr.empty()) {
171  normalized.append(std::move(curStr), curFormat);
172  }
173  curStr = str;
174  curFormat = format;
175  }
176  }
177  if (!curStr.empty()) {
178  normalized.append(std::move(curStr), curFormat);
179  }
180  normalized.setCursor(cursor());
181  return normalized;
182 }
183 
184 } // namespace fcitx
std::vector< Text > splitByLine() const
Split Text object into lines.
Definition: text.cpp:135
Formatted string commonly used in user interface.
size_t length(Iter start, Iter end)
Return the number UTF-8 characters in the string iterator range.
Definition: utf8.h:33
Definition: action.cpp:17
C++ Utility functions for handling utf8 strings.
std::vector< std::string > split(std::string_view str, std::string_view delim, SplitBehavior behavior)
Split the string by delim.
A class represents a formatted string.
Definition: text.h:27
Text normalize() const
Remove empty string piece and merge the string with same format.
Definition: text.cpp:157
Enum flag for text formatting.
void setCursor(int pos=-1)
Set cursor by byte.
Definition: text.cpp:53
bool replaceInvalidInplace(std::string &str, char replacement)
Replace invalid UTF-8 sequences in-place with given byte.
Definition: utf8.cpp:30
Class provides bit flag support for Enum.
Definition: flags.h:33
int cursor() const
Get cursor by byte.
Definition: text.cpp:48
String handle utilities.