Refactor String, use a common StringOps interface, hide std::string
This commit is contained in:
parent
a0cf75ec39
commit
3c1a325b6f
|
@ -53,7 +53,7 @@ Buffer* create_buffer_from_data(StringView data, StringView name,
|
||||||
|
|
||||||
const char* pos = data.begin();
|
const char* pos = data.begin();
|
||||||
if (data.length() >= 3 and
|
if (data.length() >= 3 and
|
||||||
data[0] == '\xEF' and data[1] == '\xBB' and data[2] == '\xBF')
|
data[0_byte] == '\xEF' and data[1_byte] == '\xBB' and data[2_byte] == '\xBF')
|
||||||
{
|
{
|
||||||
bom = true;
|
bom = true;
|
||||||
pos = data.begin() + 3;
|
pos = data.begin() + 3;
|
||||||
|
@ -81,7 +81,7 @@ Buffer* create_buffer_from_data(StringView data, StringView name,
|
||||||
if (buffer)
|
if (buffer)
|
||||||
buffer->reload(std::move(lines), fs_timestamp);
|
buffer->reload(std::move(lines), fs_timestamp);
|
||||||
else
|
else
|
||||||
buffer = new Buffer{name, flags, std::move(lines), fs_timestamp};
|
buffer = new Buffer{name.str(), flags, std::move(lines), fs_timestamp};
|
||||||
|
|
||||||
OptionManager& options = buffer->options();
|
OptionManager& options = buffer->options();
|
||||||
options.get_local_option("eolformat").set<String>(crlf ? "crlf" : "lf");
|
options.get_local_option("eolformat").set<String>(crlf ? "crlf" : "lf");
|
||||||
|
|
|
@ -257,6 +257,11 @@ StringView Client::get_env_var(const String& name) const
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringView Client::get_env_var(StringView name) const
|
||||||
|
{
|
||||||
|
return get_env_var(name.str());
|
||||||
|
}
|
||||||
|
|
||||||
void Client::on_option_changed(const Option& option)
|
void Client::on_option_changed(const Option& option)
|
||||||
{
|
{
|
||||||
if (option.name() == "ui_options")
|
if (option.name() == "ui_options")
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
void change_buffer(Buffer& buffer);
|
void change_buffer(Buffer& buffer);
|
||||||
|
|
||||||
StringView get_env_var(const String& name) const;
|
StringView get_env_var(const String& name) const;
|
||||||
|
StringView get_env_var(StringView name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void on_option_changed(const Option& option) override;
|
void on_option_changed(const Option& option) override;
|
||||||
|
|
|
@ -119,7 +119,7 @@ String get_until_delimiter(StringView base, ByteCount& pos,
|
||||||
}
|
}
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
return base.substr(start, pos - start);
|
return base.substr(start, pos - start).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct unknown_expand : parse_error
|
struct unknown_expand : parse_error
|
||||||
|
@ -313,7 +313,7 @@ String eval_token(const Token& token, Context& context,
|
||||||
return ShellManager::instance().eval(content, context, shell_params,
|
return ShellManager::instance().eval(content, context, shell_params,
|
||||||
env_vars);
|
env_vars);
|
||||||
case Token::Type::RegisterExpand:
|
case Token::Type::RegisterExpand:
|
||||||
return context.main_sel_register_value(content);
|
return context.main_sel_register_value(content).str();
|
||||||
case Token::Type::OptionExpand:
|
case Token::Type::OptionExpand:
|
||||||
return context.options()[content].get_as_string();
|
return context.options()[content].get_as_string();
|
||||||
case Token::Type::ValExpand:
|
case Token::Type::ValExpand:
|
||||||
|
|
|
@ -47,7 +47,7 @@ Buffer* open_fifo(StringView name, StringView filename, bool scroll)
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
throw runtime_error("unable to open " + filename);
|
throw runtime_error("unable to open " + filename);
|
||||||
|
|
||||||
return create_fifo_buffer(name, fd, scroll);
|
return create_fifo_buffer(name.str(), fd, scroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PerArgumentCommandCompleter filename_completer({
|
const PerArgumentCommandCompleter filename_completer({
|
||||||
|
@ -69,9 +69,9 @@ static CandidateList complete_buffer_name(StringView prefix, ByteCount cursor_po
|
||||||
StringView match_name = name;
|
StringView match_name = name;
|
||||||
if (not include_dirs and buffer->flags() & Buffer::Flags::File)
|
if (not include_dirs and buffer->flags() & Buffer::Flags::File)
|
||||||
{
|
{
|
||||||
ByteCount pos = name.find_last_of('/');
|
auto it = find(reversed(name), '/');
|
||||||
if (pos != (int)String::npos)
|
if (it != name.rend())
|
||||||
match_name = name.substr(pos+1);
|
match_name = StringView{it.base() + 2, name.end()};
|
||||||
}
|
}
|
||||||
if (prefix_match(match_name, prefix))
|
if (prefix_match(match_name, prefix))
|
||||||
prefix_result.push_back(name);
|
prefix_result.push_back(name);
|
||||||
|
@ -434,7 +434,7 @@ const CommandDesc namebuf_cmd = {
|
||||||
Completions complete_highlighter(const Context& context,
|
Completions complete_highlighter(const Context& context,
|
||||||
StringView arg, ByteCount pos_in_token, bool only_group)
|
StringView arg, ByteCount pos_in_token, bool only_group)
|
||||||
{
|
{
|
||||||
const bool shared = not arg.empty() and arg[0] == '/';
|
const bool shared = not arg.empty() and arg[0_byte] == '/';
|
||||||
if (shared)
|
if (shared)
|
||||||
{
|
{
|
||||||
auto& group = DefinedHighlighters::instance();
|
auto& group = DefinedHighlighters::instance();
|
||||||
|
@ -480,7 +480,7 @@ Highlighter& get_highlighter(const Context& context, StringView path)
|
||||||
throw runtime_error("group path should not be empty");
|
throw runtime_error("group path should not be empty");
|
||||||
|
|
||||||
Highlighter* root = nullptr;
|
Highlighter* root = nullptr;
|
||||||
if (path[0] == '/')
|
if (path[0_byte] == '/')
|
||||||
{
|
{
|
||||||
root = &DefinedHighlighters::instance();
|
root = &DefinedHighlighters::instance();
|
||||||
path = path.substr(1_byte);
|
path = path.substr(1_byte);
|
||||||
|
@ -603,12 +603,12 @@ const CommandDesc add_hook_cmd = {
|
||||||
|
|
||||||
if (regex_match(param.begin(), param.end(), regex))
|
if (regex_match(param.begin(), param.end(), regex))
|
||||||
CommandManager::instance().execute(command, context, {},
|
CommandManager::instance().execute(command, context, {},
|
||||||
{ { "hook_param", param } });
|
{ { "hook_param", param.str() } });
|
||||||
};
|
};
|
||||||
StringView group;
|
StringView group;
|
||||||
if (parser.has_option("group"))
|
if (parser.has_option("group"))
|
||||||
group = parser.option_value("group");
|
group = parser.option_value("group");
|
||||||
get_scope(parser[0], context).hooks().add_hook(parser[1], group, hook_func);
|
get_scope(parser[0], context).hooks().add_hook(parser[1], group.str(), hook_func);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -866,7 +866,7 @@ const CommandDesc debug_cmd = {
|
||||||
{
|
{
|
||||||
size_t count = domain_allocated_bytes[domain];
|
size_t count = domain_allocated_bytes[domain];
|
||||||
total += count;
|
total += count;
|
||||||
write_debug(" "_sv + domain_name((MemoryDomain)domain) + ": " + to_string(count));
|
write_debug(" "_str + domain_name((MemoryDomain)domain) + ": " + to_string(count));
|
||||||
}
|
}
|
||||||
write_debug(" Total: " + to_string(total));
|
write_debug(" Total: " + to_string(total));
|
||||||
#if defined(__GLIBC__) || defined(__CYGWIN__)
|
#if defined(__GLIBC__) || defined(__CYGWIN__)
|
||||||
|
@ -1254,7 +1254,7 @@ const CommandDesc prompt_cmd = {
|
||||||
{
|
{
|
||||||
if (params[1].length() != 1)
|
if (params[1].length() != 1)
|
||||||
throw runtime_error("register name should be a single character");
|
throw runtime_error("register name should be a single character");
|
||||||
const char reg = params[1][0];
|
const char reg = params[1][0_byte];
|
||||||
const String& command = params[2];
|
const String& command = params[2];
|
||||||
|
|
||||||
String initstr;
|
String initstr;
|
||||||
|
@ -1267,7 +1267,7 @@ const CommandDesc prompt_cmd = {
|
||||||
{
|
{
|
||||||
if (event != PromptEvent::Validate)
|
if (event != PromptEvent::Validate)
|
||||||
return;
|
return;
|
||||||
RegisterManager::instance()[reg] = ConstArrayView<String>(str);
|
RegisterManager::instance()[reg] = ConstArrayView<String>(str.str());
|
||||||
|
|
||||||
CommandManager::instance().execute(command, context);
|
CommandManager::instance().execute(command, context);
|
||||||
});
|
});
|
||||||
|
@ -1344,12 +1344,11 @@ const CommandDesc info_cmd = {
|
||||||
if (parser.has_option("anchor"))
|
if (parser.has_option("anchor"))
|
||||||
{
|
{
|
||||||
auto anchor = parser.option_value("anchor");
|
auto anchor = parser.option_value("anchor");
|
||||||
size_t dot = anchor.find_first_of('.');
|
auto dot = find(anchor, '.');
|
||||||
if (dot == String::npos)
|
if (dot == anchor.end())
|
||||||
throw runtime_error("expected <line>.<column> for anchor");
|
throw runtime_error("expected <line>.<column> for anchor");
|
||||||
ByteCount dotb = (int)dot;
|
ByteCoord coord{str_to_int({anchor.begin(), dot})-1,
|
||||||
ByteCoord coord{str_to_int(anchor.substr(0, dotb))-1,
|
str_to_int({dot+1, anchor.end()})-1};
|
||||||
str_to_int(anchor.substr(dotb+1))-1};
|
|
||||||
pos = context.window().display_position(coord);
|
pos = context.window().display_position(coord);
|
||||||
style = InfoStyle::Inline;
|
style = InfoStyle::Inline;
|
||||||
if (parser.has_option("placement"))
|
if (parser.has_option("placement"))
|
||||||
|
|
|
@ -49,7 +49,7 @@ void DisplayAtom::trim_begin(CharCount count)
|
||||||
m_begin = utf8::advance(m_buffer->iterator_at(m_begin),
|
m_begin = utf8::advance(m_buffer->iterator_at(m_begin),
|
||||||
m_buffer->iterator_at(m_end), count).coord();
|
m_buffer->iterator_at(m_end), count).coord();
|
||||||
else
|
else
|
||||||
m_text = m_text.substr(count);
|
m_text = m_text.substr(count).str();
|
||||||
check_invariant();
|
check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ void DisplayAtom::trim_end(CharCount count)
|
||||||
m_end = utf8::advance(m_buffer->iterator_at(m_end),
|
m_end = utf8::advance(m_buffer->iterator_at(m_end),
|
||||||
m_buffer->iterator_at(m_begin), -count).coord();
|
m_buffer->iterator_at(m_begin), -count).coord();
|
||||||
else
|
else
|
||||||
m_text = m_text.substr(0, m_text.char_length() - count);
|
m_text = m_text.substr(0, m_text.char_length() - count).str();
|
||||||
check_invariant();
|
check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/file.cc
14
src/file.cc
|
@ -26,8 +26,8 @@ namespace Kakoune
|
||||||
|
|
||||||
String parse_filename(StringView filename)
|
String parse_filename(StringView filename)
|
||||||
{
|
{
|
||||||
if (filename.length() >= 1 and filename[0] == '~' and
|
if (filename.length() >= 1 and filename[0_byte] == '~' and
|
||||||
(filename.length() == 1 or filename[1] == '/'))
|
(filename.length() == 1 or filename[1_byte] == '/'))
|
||||||
return parse_filename("$HOME"_str + filename.substr(1_byte));
|
return parse_filename("$HOME"_str + filename.substr(1_byte));
|
||||||
|
|
||||||
ByteCount pos = 0;
|
ByteCount pos = 0;
|
||||||
|
@ -90,7 +90,7 @@ String real_path(StringView filename)
|
||||||
|
|
||||||
auto it = find(existing.rbegin(), existing.rend(), '/');
|
auto it = find(existing.rbegin(), existing.rend(), '/');
|
||||||
if (it == existing.rend())
|
if (it == existing.rend())
|
||||||
return filename;
|
return filename.str();
|
||||||
|
|
||||||
existing = StringView{existing.begin(), it.base()-1};
|
existing = StringView{existing.begin(), it.base()-1};
|
||||||
non_existing = StringView{it.base(), filename.end()};
|
non_existing = StringView{it.base(), filename.end()};
|
||||||
|
@ -105,7 +105,7 @@ String compact_path(StringView filename)
|
||||||
getcwd(cwd, 1024);
|
getcwd(cwd, 1024);
|
||||||
String real_cwd = real_path(cwd) + "/";
|
String real_cwd = real_path(cwd) + "/";
|
||||||
if (prefix_match(real_filename, real_cwd))
|
if (prefix_match(real_filename, real_cwd))
|
||||||
return real_filename.substr(real_cwd.length());
|
return real_filename.substr(real_cwd.length()).str();
|
||||||
|
|
||||||
const char* home = getenv("HOME");
|
const char* home = getenv("HOME");
|
||||||
if (home)
|
if (home)
|
||||||
|
@ -258,14 +258,14 @@ void write_buffer_to_backup_file(Buffer& buffer)
|
||||||
String find_file(StringView filename, ConstArrayView<String> paths)
|
String find_file(StringView filename, ConstArrayView<String> paths)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
if (filename.length() > 1 and filename[0] == '/')
|
if (filename.length() > 1 and filename[0_byte] == '/')
|
||||||
{
|
{
|
||||||
if (stat(filename.zstr(), &buf) == 0 and S_ISREG(buf.st_mode))
|
if (stat(filename.zstr(), &buf) == 0 and S_ISREG(buf.st_mode))
|
||||||
return filename.str();
|
return filename.str();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
if (filename.length() > 2 and
|
if (filename.length() > 2 and
|
||||||
filename[0] == '~' and filename[1] == '/')
|
filename[0_byte] == '~' and filename[1_byte] == '/')
|
||||||
{
|
{
|
||||||
String candidate = getenv("HOME") + filename.substr(1_byte).str();
|
String candidate = getenv("HOME") + filename.substr(1_byte).str();
|
||||||
if (stat(candidate.c_str(), &buf) == 0 and S_ISREG(buf.st_mode))
|
if (stat(candidate.c_str(), &buf) == 0 and S_ISREG(buf.st_mode))
|
||||||
|
@ -386,7 +386,7 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
||||||
Vector<String> res;
|
Vector<String> res;
|
||||||
for (auto dir : split(getenv("PATH"), ':'))
|
for (auto dir : split(getenv("PATH"), ':'))
|
||||||
{
|
{
|
||||||
String dirname = dir;
|
String dirname = dir.str();
|
||||||
if (not dirname.empty() and dirname.back() != '/')
|
if (not dirname.empty() and dirname.back() != '/')
|
||||||
dirname += '/';
|
dirname += '/';
|
||||||
|
|
||||||
|
|
|
@ -264,9 +264,9 @@ public:
|
||||||
if (not regex_match(it->begin(), it->end(), res, face_spec_ex))
|
if (not regex_match(it->begin(), it->end(), res, face_spec_ex))
|
||||||
throw runtime_error("wrong face spec: '" + *it +
|
throw runtime_error("wrong face spec: '" + *it +
|
||||||
"' expected <capture>:<facespec>");
|
"' expected <capture>:<facespec>");
|
||||||
get_face(res[2].str()); // throw if wrong face spec
|
get_face({res[2].first, res[2].second}); // throw if wrong face spec
|
||||||
int capture = str_to_int(res[1].str());
|
int capture = str_to_int({res[1].first, res[1].second});
|
||||||
faces.emplace_back(capture, res[2].str());
|
faces.emplace_back(capture, String{res[2].first, res[2].second});
|
||||||
}
|
}
|
||||||
|
|
||||||
String id = "hlregex'" + params[0] + "'";
|
String id = "hlregex'" + params[0] + "'";
|
||||||
|
@ -711,7 +711,8 @@ void expand_unprintable(const Context& context, HighlightFlags flags, DisplayBuf
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "U+" << std::hex << cp;
|
oss << "U+" << std::hex << cp;
|
||||||
String str = oss.str();
|
const auto& stdstr = oss.str();
|
||||||
|
String str{stdstr.begin(), stdstr.end()};
|
||||||
if (it.coord() != atom_it->begin())
|
if (it.coord() != atom_it->begin())
|
||||||
atom_it = ++line.split(atom_it, it.coord());
|
atom_it = ++line.split(atom_it, it.coord());
|
||||||
if (next.coord() < atom_it->end())
|
if (next.coord() < atom_it->end())
|
||||||
|
|
|
@ -51,7 +51,7 @@ void HookManager::run_hook(StringView hook_name,
|
||||||
for (auto& hook : hook_list_it->second)
|
for (auto& hook : hook_list_it->second)
|
||||||
{
|
{
|
||||||
if (not hook.first.empty() and not disabled_hooks.empty() and
|
if (not hook.first.empty() and not disabled_hooks.empty() and
|
||||||
regex_match(hook.first, disabled_hooks))
|
regex_match(hook.first.begin(), hook.first.end(), disabled_hooks))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
@ -65,7 +65,7 @@ public:
|
||||||
if (it != m_content.end())
|
if (it != m_content.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
append({ id, Value{} });
|
append({ id.str(), Value{} });
|
||||||
return (m_content.end()-1)->second;
|
return (m_content.end()-1)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ public:
|
||||||
if (m_params.reg != '"')
|
if (m_params.reg != '"')
|
||||||
{
|
{
|
||||||
atoms.push_back({ "; reg=", Face(Colors::Yellow) });
|
atoms.push_back({ "; reg=", Face(Colors::Yellow) });
|
||||||
atoms.push_back({ StringView(m_params.reg), Face(Colors::Green) });
|
atoms.push_back({ StringView(m_params.reg).str(), Face(Colors::Green) });
|
||||||
}
|
}
|
||||||
return atoms;
|
return atoms;
|
||||||
}
|
}
|
||||||
|
@ -325,12 +325,12 @@ public:
|
||||||
m_display_pos = m_cursor_pos + 1 - width;
|
m_display_pos = m_cursor_pos + 1 - width;
|
||||||
|
|
||||||
if (m_cursor_pos == m_line.char_length())
|
if (m_cursor_pos == m_line.char_length())
|
||||||
return DisplayLine{{ {m_line.substr(m_display_pos, width-1), get_face("StatusLine")},
|
return DisplayLine{{ {m_line.substr(m_display_pos, width-1).str(), get_face("StatusLine")},
|
||||||
{" "_str, get_face("StatusCursor")} }};
|
{" "_str, get_face("StatusCursor")} }};
|
||||||
else
|
else
|
||||||
return DisplayLine({ { m_line.substr(m_display_pos, m_cursor_pos - m_display_pos), get_face("StatusLine") },
|
return DisplayLine({ { m_line.substr(m_display_pos, m_cursor_pos - m_display_pos).str(), get_face("StatusLine") },
|
||||||
{ m_line.substr(m_cursor_pos,1), get_face("StatusCursor") },
|
{ m_line.substr(m_cursor_pos,1).str(), get_face("StatusCursor") },
|
||||||
{ m_line.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1), get_face("StatusLine") } });
|
{ m_line.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1).str(), get_face("StatusLine") } });
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
CharCount m_cursor_pos = 0;
|
CharCount m_cursor_pos = 0;
|
||||||
|
@ -473,7 +473,7 @@ String common_prefix(ConstArrayView<String> strings)
|
||||||
while (common_len < len and str[common_len] == res[common_len])
|
while (common_len < len and str[common_len] == res[common_len])
|
||||||
++common_len;
|
++common_len;
|
||||||
if (common_len != res.length())
|
if (common_len != res.length())
|
||||||
res = res.substr(0, common_len);
|
res = res.substr(0, common_len).str();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ public:
|
||||||
Prompt(InputHandler& input_handler, StringView prompt,
|
Prompt(InputHandler& input_handler, StringView prompt,
|
||||||
String initstr, Face face, Completer completer,
|
String initstr, Face face, Completer completer,
|
||||||
PromptCallback callback)
|
PromptCallback callback)
|
||||||
: InputMode(input_handler), m_prompt(prompt), m_prompt_face(face),
|
: InputMode(input_handler), m_prompt(prompt.str()), m_prompt_face(face),
|
||||||
m_completer(completer), m_callback(callback),
|
m_completer(completer), m_callback(callback),
|
||||||
m_autoshowcompl{context().options()["autoshowcompl"].get<bool>()}
|
m_autoshowcompl{context().options()["autoshowcompl"].get<bool>()}
|
||||||
{
|
{
|
||||||
|
@ -600,7 +600,7 @@ public:
|
||||||
String prefix = common_prefix(candidates);
|
String prefix = common_prefix(candidates);
|
||||||
if (m_completions.end - m_completions.start > prefix.length())
|
if (m_completions.end - m_completions.start > prefix.length())
|
||||||
prefix = line.substr(m_completions.start,
|
prefix = line.substr(m_completions.start,
|
||||||
m_completions.end - m_completions.start);
|
m_completions.end - m_completions.start).str();
|
||||||
|
|
||||||
if (not prefix.empty())
|
if (not prefix.empty())
|
||||||
{
|
{
|
||||||
|
@ -742,7 +742,7 @@ private:
|
||||||
History::iterator it;
|
History::iterator it;
|
||||||
while ((it = find(history, entry)) != history.end())
|
while ((it = find(history, entry)) != history.end())
|
||||||
history.erase(it);
|
history.erase(it);
|
||||||
history.push_back(entry);
|
history.push_back(entry.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
UnorderedMap<String, Prompt::History, MemoryDomain::History> Prompt::ms_history;
|
UnorderedMap<String, Prompt::History, MemoryDomain::History> Prompt::ms_history;
|
||||||
|
|
|
@ -119,7 +119,7 @@ InsertCompletion complete_word(const Buffer& buffer, ByteCoord cursor_pos)
|
||||||
ComplAndDescList result;
|
ComplAndDescList result;
|
||||||
result.reserve(matches.size());
|
result.reserve(matches.size());
|
||||||
for (auto& m : matches)
|
for (auto& m : matches)
|
||||||
result.emplace_back(m, "");
|
result.emplace_back(m.str(), "");
|
||||||
|
|
||||||
return { begin.coord(), cursor_pos, std::move(result), buffer.timestamp() };
|
return { begin.coord(), cursor_pos, std::move(result), buffer.timestamp() };
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ InsertCompletion complete_filename(const Buffer& buffer, ByteCoord cursor_pos,
|
||||||
if (not dir.empty() and dir.back() != '/')
|
if (not dir.empty() and dir.back() != '/')
|
||||||
dir += '/';
|
dir += '/';
|
||||||
for (auto& filename : Kakoune::complete_filename(dir + prefix, Regex{}))
|
for (auto& filename : Kakoune::complete_filename(dir + prefix, Regex{}))
|
||||||
res.emplace_back(filename.substr(dir.length()), "");
|
res.emplace_back(filename.substr(dir.length()).str(), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (res.empty())
|
if (res.empty())
|
||||||
|
@ -178,16 +178,17 @@ InsertCompletion complete_option(const Buffer& buffer, ByteCoord cursor_pos,
|
||||||
MatchResults<String::const_iterator> match;
|
MatchResults<String::const_iterator> match;
|
||||||
if (regex_match(desc.begin(), desc.end(), match, re))
|
if (regex_match(desc.begin(), desc.end(), match, re))
|
||||||
{
|
{
|
||||||
ByteCoord coord{ str_to_int(match[1].str()) - 1, str_to_int(match[2].str()) - 1 };
|
ByteCoord coord{ str_to_int({match[1].first, match[1].second}) - 1,
|
||||||
|
str_to_int({match[2].first, match[2].second}) - 1 };
|
||||||
if (not buffer.is_valid(coord))
|
if (not buffer.is_valid(coord))
|
||||||
return {};
|
return {};
|
||||||
auto end = coord;
|
auto end = coord;
|
||||||
if (match[3].matched)
|
if (match[3].matched)
|
||||||
{
|
{
|
||||||
ByteCount len = str_to_int(match[3].str());
|
ByteCount len = str_to_int({match[3].first, match[3].second});
|
||||||
end = buffer.advance(coord, len);
|
end = buffer.advance(coord, len);
|
||||||
}
|
}
|
||||||
size_t timestamp = (size_t)str_to_int(match[4].str());
|
size_t timestamp = (size_t)str_to_int({match[4].first, match[4].second});
|
||||||
auto changes = buffer.changes_since(timestamp);
|
auto changes = buffer.changes_since(timestamp);
|
||||||
if (find_if(changes, [&](const Buffer::Change& change){
|
if (find_if(changes, [&](const Buffer::Change& change){
|
||||||
return change.begin < coord;
|
return change.begin < coord;
|
||||||
|
@ -204,7 +205,7 @@ InsertCompletion complete_option(const Buffer& buffer, ByteCoord cursor_pos,
|
||||||
{
|
{
|
||||||
auto splitted = split(*it, '@');
|
auto splitted = split(*it, '@');
|
||||||
if (not splitted.empty() and prefix_match(splitted[0], prefix))
|
if (not splitted.empty() and prefix_match(splitted[0], prefix))
|
||||||
res.emplace_back(splitted[0], splitted.size() > 1 ? splitted[1] : "");
|
res.emplace_back(splitted[0].str(), splitted.size() > 1 ? splitted[1].str() : "");
|
||||||
}
|
}
|
||||||
return { coord, end, std::move(res), timestamp };
|
return { coord, end, std::move(res), timestamp };
|
||||||
}
|
}
|
||||||
|
@ -222,7 +223,7 @@ InsertCompletion complete_line(const Buffer& buffer, ByteCoord cursor_pos)
|
||||||
continue;
|
continue;
|
||||||
ByteCount len = buffer[l].length();
|
ByteCount len = buffer[l].length();
|
||||||
if (len > cursor_pos.column and std::equal(prefix.begin(), prefix.end(), buffer[l].begin()))
|
if (len > cursor_pos.column and std::equal(prefix.begin(), prefix.end(), buffer[l].begin()))
|
||||||
res.emplace_back(buffer[l].substr(0_byte, len-1), "");
|
res.emplace_back(buffer[l].substr(0_byte, len-1).str(), "");
|
||||||
}
|
}
|
||||||
if (res.empty())
|
if (res.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -64,9 +64,9 @@ KeyList parse_keys(StringView str)
|
||||||
Key::Modifiers modifier = Key::Modifiers::None;
|
Key::Modifiers modifier = Key::Modifiers::None;
|
||||||
|
|
||||||
StringView desc{it.base()+1, end_it.base()};
|
StringView desc{it.base()+1, end_it.base()};
|
||||||
if (desc.length() > 2 and desc[1] == '-')
|
if (desc.length() > 2 and desc[1_byte] == '-')
|
||||||
{
|
{
|
||||||
switch(tolower(desc[0]))
|
switch(tolower(desc[0_byte]))
|
||||||
{
|
{
|
||||||
case 'c': modifier = Key::Modifiers::Control; break;
|
case 'c': modifier = Key::Modifiers::Control; break;
|
||||||
case 'a': modifier = Key::Modifiers::Alt; break;
|
case 'a': modifier = Key::Modifiers::Alt; break;
|
||||||
|
@ -82,7 +82,7 @@ KeyList parse_keys(StringView str)
|
||||||
result.push_back(canonicalize_ifn({ modifier, name_it->key }));
|
result.push_back(canonicalize_ifn({ modifier, name_it->key }));
|
||||||
else if (desc.char_length() == 1)
|
else if (desc.char_length() == 1)
|
||||||
result.push_back(Key{ modifier, desc[0_char] });
|
result.push_back(Key{ modifier, desc[0_char] });
|
||||||
else if (tolower(desc[0]) == 'f' and desc.length() <= 3)
|
else if (tolower(desc[0_byte]) == 'f' and desc.length() <= 3)
|
||||||
{
|
{
|
||||||
int val = str_to_int(desc.substr(1_byte));
|
int val = str_to_int(desc.substr(1_byte));
|
||||||
if (val >= 1 and val <= 12)
|
if (val >= 1 and val <= 12)
|
||||||
|
|
24
src/main.cc
24
src/main.cc
|
@ -37,10 +37,10 @@ void run_unit_tests();
|
||||||
String runtime_directory()
|
String runtime_directory()
|
||||||
{
|
{
|
||||||
String bin_path = get_kak_binary_path();
|
String bin_path = get_kak_binary_path();
|
||||||
size_t last_slash = bin_path.find_last_of('/');
|
auto it = find(reversed(bin_path), '/');
|
||||||
if (last_slash == String::npos)
|
if (it == bin_path.rend())
|
||||||
throw runtime_error("unable to determine runtime directory");
|
throw runtime_error("unable to determine runtime directory");
|
||||||
return bin_path.substr(0_byte, (int)last_slash) + "/../share/kak";
|
return StringView{bin_path.begin(), it.base()-1} + "/../share/kak";
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_env_vars()
|
void register_env_vars()
|
||||||
|
@ -54,7 +54,7 @@ void register_env_vars()
|
||||||
{ return context.buffer().display_name(); }
|
{ return context.buffer().display_name(); }
|
||||||
}, {
|
}, {
|
||||||
"buffile",
|
"buffile",
|
||||||
[](StringView name, const Context& context) -> String
|
[](StringView name, const Context& context)
|
||||||
{ return context.buffer().name(); }
|
{ return context.buffer().name(); }
|
||||||
}, {
|
}, {
|
||||||
"buflist",
|
"buflist",
|
||||||
|
@ -85,19 +85,19 @@ void register_env_vars()
|
||||||
{ return context.options()[name.substr(4_byte)].get_as_string(); }
|
{ return context.options()[name.substr(4_byte)].get_as_string(); }
|
||||||
}, {
|
}, {
|
||||||
"reg_.+",
|
"reg_.+",
|
||||||
[](StringView name, const Context& context) -> String
|
[](StringView name, const Context& context)
|
||||||
{ return context.main_sel_register_value(name.substr(4_byte)); }
|
{ return context.main_sel_register_value(name.substr(4_byte)).str(); }
|
||||||
}, {
|
}, {
|
||||||
"client_env_.+",
|
"client_env_.+",
|
||||||
[](StringView name, const Context& context) -> String
|
[](StringView name, const Context& context)
|
||||||
{ return context.client().get_env_var(name.substr(11_byte)); }
|
{ return context.client().get_env_var(name.substr(11_byte)).str(); }
|
||||||
}, {
|
}, {
|
||||||
"session",
|
"session",
|
||||||
[](StringView name, const Context& context) -> String
|
[](StringView name, const Context& context)
|
||||||
{ return Server::instance().session(); }
|
{ return Server::instance().session(); }
|
||||||
}, {
|
}, {
|
||||||
"client",
|
"client",
|
||||||
[](StringView name, const Context& context) -> String
|
[](StringView name, const Context& context)
|
||||||
{ return context.name(); }
|
{ return context.name(); }
|
||||||
}, {
|
}, {
|
||||||
"cursor_line",
|
"cursor_line",
|
||||||
|
@ -356,7 +356,7 @@ int run_server(StringView session, StringView init_command,
|
||||||
|
|
||||||
write_debug("*** This is the debug buffer, where debug info will be written ***");
|
write_debug("*** This is the debug buffer, where debug info will be written ***");
|
||||||
|
|
||||||
Server server(session.empty() ? to_string(getpid()) : String{session});
|
Server server(session.empty() ? to_string(getpid()) : session.str());
|
||||||
|
|
||||||
if (not ignore_kakrc) try
|
if (not ignore_kakrc) try
|
||||||
{
|
{
|
||||||
|
@ -385,7 +385,7 @@ int run_server(StringView session, StringView init_command,
|
||||||
for (auto& file : reversed(files))
|
for (auto& file : reversed(files))
|
||||||
{
|
{
|
||||||
if (not create_buffer_from_file(file))
|
if (not create_buffer_from_file(file))
|
||||||
new Buffer(file, Buffer::Flags::New | Buffer::Flags::File);
|
new Buffer(file.str(), Buffer::Flags::New | Buffer::Flags::File);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Kakoune::runtime_error& error)
|
catch (Kakoune::runtime_error& error)
|
||||||
|
|
|
@ -591,7 +591,7 @@ void NCursesUI::menu_show(ConstArrayView<String> items,
|
||||||
const CharCount maxlen = min((int)maxsize.column-2, 200);
|
const CharCount maxlen = min((int)maxsize.column-2, 200);
|
||||||
for (auto& item : items)
|
for (auto& item : items)
|
||||||
{
|
{
|
||||||
m_items.push_back(item.substr(0_char, maxlen));
|
m_items.push_back(item.substr(0_char, maxlen).str());
|
||||||
longest = max(longest, m_items.back().char_length());
|
longest = max(longest, m_items.back().char_length());
|
||||||
}
|
}
|
||||||
longest += 1;
|
longest += 1;
|
||||||
|
|
|
@ -375,7 +375,7 @@ void pipe(Context& context, NormalParams)
|
||||||
real_cmd = context.main_sel_register_value("|");
|
real_cmd = context.main_sel_register_value("|");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RegisterManager::instance()['|'] = String{cmdline};
|
RegisterManager::instance()['|'] = cmdline.str();
|
||||||
real_cmd = cmdline;
|
real_cmd = cmdline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ void pipe(Context& context, NormalParams)
|
||||||
{}, EnvVarMap{});
|
{}, EnvVarMap{});
|
||||||
if ((insert_eol or sel.max() == buffer.back_coord()) and
|
if ((insert_eol or sel.max() == buffer.back_coord()) and
|
||||||
str.back() == '\n')
|
str.back() == '\n')
|
||||||
str = str.substr(0, str.length()-1);
|
str = str.substr(0, str.length()-1).str();
|
||||||
strings.push_back(std::move(str));
|
strings.push_back(std::move(str));
|
||||||
}
|
}
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
|
@ -428,7 +428,7 @@ void insert_output(Context& context, NormalParams)
|
||||||
real_cmd = context.main_sel_register_value("|");
|
real_cmd = context.main_sel_register_value("|");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RegisterManager::instance()['|'] = String{cmdline};
|
RegisterManager::instance()['|'] = cmdline.str();
|
||||||
real_cmd = cmdline;
|
real_cmd = cmdline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +617,7 @@ void search(Context& context, NormalParams)
|
||||||
if (ex.empty())
|
if (ex.empty())
|
||||||
ex = Regex{context.main_sel_register_value("/").str()};
|
ex = Regex{context.main_sel_register_value("/").str()};
|
||||||
else if (event == PromptEvent::Validate)
|
else if (event == PromptEvent::Validate)
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = ex.str();
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
select_next_match<direction, mode>(context.buffer(), context.selections(), ex);
|
select_next_match<direction, mode>(context.buffer(), context.selections(), ex);
|
||||||
});
|
});
|
||||||
|
@ -674,7 +674,7 @@ void select_regex(Context& context, NormalParams)
|
||||||
if (ex.empty())
|
if (ex.empty())
|
||||||
ex = Regex{context.main_sel_register_value("/").str()};
|
ex = Regex{context.main_sel_register_value("/").str()};
|
||||||
else if (event == PromptEvent::Validate)
|
else if (event == PromptEvent::Validate)
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = ex.str();
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
select_all_matches(context.selections(), ex);
|
select_all_matches(context.selections(), ex);
|
||||||
});
|
});
|
||||||
|
@ -686,7 +686,7 @@ void split_regex(Context& context, NormalParams)
|
||||||
if (ex.empty())
|
if (ex.empty())
|
||||||
ex = Regex{context.main_sel_register_value("/").str()};
|
ex = Regex{context.main_sel_register_value("/").str()};
|
||||||
else if (event == PromptEvent::Validate)
|
else if (event == PromptEvent::Validate)
|
||||||
RegisterManager::instance()['/'] = String{ex.str()};
|
RegisterManager::instance()['/'] = ex.str();
|
||||||
if (not ex.empty() and not ex.str().empty())
|
if (not ex.empty() and not ex.str().empty())
|
||||||
split_selections(context.selections(), ex);
|
split_selections(context.selections(), ex);
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
inline String option_to_string(StringView opt) { return opt; }
|
inline String option_to_string(StringView opt) { return opt.str(); }
|
||||||
inline void option_from_string(StringView str, String& opt) { opt = str; }
|
inline void option_from_string(StringView str, String& opt) { opt = str.str(); }
|
||||||
|
|
||||||
inline String option_to_string(int opt) { return to_string(opt); }
|
inline String option_to_string(int opt) { return to_string(opt); }
|
||||||
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
|
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
|
||||||
|
|
|
@ -21,7 +21,7 @@ ParametersParser::ParametersParser(ParameterList params,
|
||||||
{
|
{
|
||||||
if (not only_pos and params[i] == "--")
|
if (not only_pos and params[i] == "--")
|
||||||
only_pos = true;
|
only_pos = true;
|
||||||
else if (not only_pos and params[i][0] == '-')
|
else if (not only_pos and params[i][0_byte] == '-')
|
||||||
{
|
{
|
||||||
auto it = m_desc.switches.find(params[i].substr(1_byte));
|
auto it = m_desc.switches.find(params[i].substr(1_byte));
|
||||||
if (it == m_desc.switches.end())
|
if (it == m_desc.switches.end())
|
||||||
|
@ -30,7 +30,7 @@ ParametersParser::ParametersParser(ParameterList params,
|
||||||
if (it->second.takes_arg)
|
if (it->second.takes_arg)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
if (i == params.size() or params[i][0] == '-')
|
if (i == params.size() or params[i][0_byte] == '-')
|
||||||
throw missing_option_value(it->first);
|
throw missing_option_value(it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ bool ParametersParser::has_option(const String& name) const
|
||||||
kak_assert(m_desc.switches.find(name) != m_desc.switches.end());
|
kak_assert(m_desc.switches.find(name) != m_desc.switches.end());
|
||||||
for (auto& param : m_params)
|
for (auto& param : m_params)
|
||||||
{
|
{
|
||||||
if (param[0] == '-' and param.substr(1_byte) == name)
|
if (param[0_byte] == '-' and param.substr(1_byte) == name)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (param == "--")
|
if (param == "--")
|
||||||
|
@ -70,7 +70,7 @@ const String& ParametersParser::option_value(const String& name) const
|
||||||
|
|
||||||
for (size_t i = 0; i < m_params.size(); ++i)
|
for (size_t i = 0; i < m_params.size(); ++i)
|
||||||
{
|
{
|
||||||
if (m_params[i][0] == '-' and m_params[i].substr(1_byte) == name)
|
if (m_params[i][0_byte] == '-' and m_params[i].substr(1_byte) == name)
|
||||||
return m_params[i+1];
|
return m_params[i+1];
|
||||||
|
|
||||||
if (m_params[i] == "--")
|
if (m_params[i] == "--")
|
||||||
|
|
|
@ -7,7 +7,8 @@ namespace Kakoune
|
||||||
|
|
||||||
String option_to_string(const Regex& re)
|
String option_to_string(const Regex& re)
|
||||||
{
|
{
|
||||||
return String{re.str()};
|
const auto& str = re.str();
|
||||||
|
return String{str.begin(), str.end()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void option_from_string(StringView str, Regex& re)
|
void option_from_string(StringView str, Regex& re)
|
||||||
|
|
16
src/regex.hh
16
src/regex.hh
|
@ -29,15 +29,27 @@ struct Regex : std::regex
|
||||||
bool operator==(const Regex& other) { return m_str == other.m_str; }
|
bool operator==(const Regex& other) { return m_str == other.m_str; }
|
||||||
bool operator!=(const Regex& other) { return m_str != other.m_str; }
|
bool operator!=(const Regex& other) { return m_str != other.m_str; }
|
||||||
|
|
||||||
StringView str() const { return m_str; }
|
const String& str() const { return m_str; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_str;
|
String m_str;
|
||||||
};
|
};
|
||||||
namespace regex_ns = std;
|
namespace regex_ns = std;
|
||||||
#else
|
#else
|
||||||
|
struct Regex : boost::regex
|
||||||
|
{
|
||||||
|
Regex() = default;
|
||||||
|
|
||||||
|
explicit Regex(StringView re, flag_type flags = ECMAScript)
|
||||||
|
: boost::regex(re.begin(), re.end(), flags) {}
|
||||||
|
|
||||||
|
template<typename Iterator>
|
||||||
|
Regex(Iterator begin, Iterator end, flag_type flags = ECMAScript)
|
||||||
|
: boost::regex(begin, end, flags) {}
|
||||||
|
|
||||||
|
String str() const { auto s = boost::regex::str(); return {s.begin(), s.end()}; }
|
||||||
|
};
|
||||||
namespace regex_ns = boost;
|
namespace regex_ns = boost;
|
||||||
using Regex = boost::regex;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
|
|
|
@ -59,7 +59,7 @@ private:
|
||||||
Register& RegisterManager::operator[](StringView reg)
|
Register& RegisterManager::operator[](StringView reg)
|
||||||
{
|
{
|
||||||
if (reg.length() == 1)
|
if (reg.length() == 1)
|
||||||
return (*this)[reg[0]];
|
return (*this)[reg[0_byte]];
|
||||||
|
|
||||||
static const IdMap<Codepoint> reg_names = {
|
static const IdMap<Codepoint> reg_names = {
|
||||||
{ "slash", '/' },
|
{ "slash", '/' },
|
||||||
|
|
|
@ -23,7 +23,7 @@ ShellManager::ShellManager()
|
||||||
new_path = path + ":"_str;
|
new_path = path + ":"_str;
|
||||||
|
|
||||||
String kak_path = get_kak_binary_path();
|
String kak_path = get_kak_binary_path();
|
||||||
StringView kak_dir = kak_path.substr(0_byte, (int)kak_path.find_last_of('/'));
|
StringView kak_dir{kak_path.begin(), find(reversed(kak_path), '/').base()-1};
|
||||||
new_path += kak_dir;
|
new_path += kak_dir;
|
||||||
setenv("PATH", new_path.c_str(), 1);
|
setenv("PATH", new_path.c_str(), 1);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ String ShellManager::pipe(StringView input,
|
||||||
StringView name = StringView(match[1].first, match[1].second);
|
StringView name = StringView(match[1].first, match[1].second);
|
||||||
kak_assert(name.length() > 0);
|
kak_assert(name.length() > 0);
|
||||||
|
|
||||||
auto local_var = env_vars.find(name);
|
auto local_var = env_vars.find(name.str());
|
||||||
if (local_var != env_vars.end())
|
if (local_var != env_vars.end())
|
||||||
setenv(("kak_" + name).c_str(), local_var->second.c_str(), 1);
|
setenv(("kak_" + name).c_str(), local_var->second.c_str(), 1);
|
||||||
else
|
else
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
bool operator<(StringView lhs, StringView rhs)
|
|
||||||
{
|
|
||||||
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<String> split(StringView str, char separator, char escape)
|
Vector<String> split(StringView str, char separator, char escape)
|
||||||
{
|
{
|
||||||
Vector<String> res;
|
Vector<String> res;
|
||||||
|
|
298
src/string.hh
298
src/string.hh
|
@ -14,56 +14,133 @@ namespace Kakoune
|
||||||
|
|
||||||
class StringView;
|
class StringView;
|
||||||
|
|
||||||
using StringBase = std::basic_string<char, std::char_traits<char>,
|
template<typename Type, typename CharType>
|
||||||
Allocator<char, MemoryDomain::String>>;
|
class StringOps
|
||||||
|
|
||||||
constexpr ByteCount strlen(const char* s)
|
|
||||||
{
|
|
||||||
return *s == 0 ? 0 : strlen(s+1) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
class String : public StringBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using value_type = CharType;
|
||||||
|
|
||||||
|
friend bool operator==(const Type& lhs, const Type& rhs)
|
||||||
|
{
|
||||||
|
return lhs.length() == rhs.length() and
|
||||||
|
std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const Type& lhs, const Type& rhs)
|
||||||
|
{
|
||||||
|
return lhs.length() != rhs.length() or
|
||||||
|
not std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<(const Type& lhs, const Type& rhs)
|
||||||
|
{
|
||||||
|
return std::lexicographical_compare(lhs.begin(), lhs.end(),
|
||||||
|
rhs.begin(), rhs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline size_t hash_value(const Type& str)
|
||||||
|
{
|
||||||
|
return hash_data(str.data(), (int)str.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
using iterator = CharType*;
|
||||||
|
using const_iterator = const CharType*;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
iterator begin() { return type().data(); }
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
const_iterator begin() const { return type().data(); }
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
iterator end() { return type().data() + (int)type().length(); }
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
const_iterator end() const { return type().data() + (int)type().length(); }
|
||||||
|
|
||||||
|
reverse_iterator rbegin() { return reverse_iterator{end()}; }
|
||||||
|
const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; }
|
||||||
|
|
||||||
|
reverse_iterator rend() { return reverse_iterator{begin()}; }
|
||||||
|
const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; }
|
||||||
|
|
||||||
|
CharType& front() { return *type().data(); }
|
||||||
|
const CharType& front() const { return *type().data(); }
|
||||||
|
CharType& back() { return type().data()[(int)type().length() - 1]; }
|
||||||
|
const CharType& back() const { return type().data()[(int)type().length() - 1]; }
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
CharType& operator[](ByteCount pos) { return type().data()[(int)pos]; }
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
const CharType& operator[](ByteCount pos) const
|
||||||
|
{ return type().data()[(int)pos]; }
|
||||||
|
|
||||||
|
Codepoint operator[](CharCount pos) const
|
||||||
|
{ return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
|
||||||
|
|
||||||
|
CharCount char_length() const { return utf8::distance(begin(), end()); }
|
||||||
|
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
bool empty() const { return type().length() == 0_byte; }
|
||||||
|
|
||||||
|
ByteCount byte_count_to(CharCount count) const
|
||||||
|
{ return utf8::advance(begin(), end(), (int)count) - begin(); }
|
||||||
|
|
||||||
|
CharCount char_count_to(ByteCount count) const
|
||||||
|
{ return utf8::distance(begin(), begin() + (int)count); }
|
||||||
|
|
||||||
|
StringView substr(ByteCount from, ByteCount length = INT_MAX) const;
|
||||||
|
StringView substr(CharCount from, CharCount length = INT_MAX) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type& type() { return *static_cast<Type*>(this); }
|
||||||
|
const Type& type() const { return *static_cast<const Type*>(this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class String : public StringOps<String, char>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Content = std::basic_string<char, std::char_traits<char>,
|
||||||
|
Allocator<char, MemoryDomain::String>>;
|
||||||
|
|
||||||
String() {}
|
String() {}
|
||||||
String(const char* content) : StringBase(content) {}
|
String(const char* content) : m_data(content) {}
|
||||||
String(StringBase content) : StringBase(std::move(content)) {}
|
String(Content content) : m_data(std::move(content)) {}
|
||||||
template<typename Char, typename Traits, typename Alloc>
|
explicit String(char content, CharCount count = 1) : m_data((size_t)(int)count, content) {}
|
||||||
String(const std::basic_string<Char, Traits, Alloc>& content) : StringBase(content.begin(), content.end()) {}
|
|
||||||
explicit String(char content, CharCount count = 1) : StringBase((size_t)(int)count, content) {}
|
|
||||||
explicit String(Codepoint cp, CharCount count = 1)
|
explicit String(Codepoint cp, CharCount count = 1)
|
||||||
{
|
{
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
utf8::dump(back_inserter(*this), cp);
|
utf8::dump(std::back_inserter(*this), cp);
|
||||||
}
|
}
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
String(Iterator begin, Iterator end) : StringBase(begin, end) {}
|
String(Iterator begin, Iterator end) : m_data(begin, end) {}
|
||||||
|
|
||||||
StringBase& stdstr() { return *this; }
|
|
||||||
const StringBase& stdstr() const { return *this; }
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
char operator[](ByteCount pos) const { return StringBase::operator[]((int)pos); }
|
char* data() { return &m_data[0]; }
|
||||||
[[gnu::always_inline]]
|
|
||||||
char& operator[](ByteCount pos) { return StringBase::operator[]((int)pos); }
|
|
||||||
Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
ByteCount length() const { return ByteCount{(int)StringBase::length()}; }
|
const char* data() const { return m_data.data(); }
|
||||||
CharCount char_length() const { return utf8::distance(begin(), end()); }
|
|
||||||
ByteCount byte_count_to(CharCount count) const { return utf8::advance(begin(), end(), (int)count) - begin(); }
|
|
||||||
CharCount char_count_to(ByteCount count) const { return utf8::distance(begin(), begin() + (int)count); }
|
|
||||||
|
|
||||||
String& operator+=(const String& other) { StringBase::operator+=(other); return *this; }
|
[[gnu::always_inline]]
|
||||||
String& operator+=(const char* other) { StringBase::operator+=(other); return *this; }
|
ByteCount length() const { return ByteCount{(int)m_data.length()}; }
|
||||||
String& operator+=(char other) { StringBase::operator+=(other); return *this; }
|
|
||||||
String& operator+=(Codepoint cp) { utf8::dump(back_inserter(*this), cp); return *this; }
|
|
||||||
|
|
||||||
StringView substr(ByteCount pos, ByteCount length = INT_MAX) const;
|
[[gnu::always_inline]]
|
||||||
StringView substr(CharCount pos, CharCount length = INT_MAX) const;
|
const char* c_str() const { return m_data.c_str(); }
|
||||||
|
|
||||||
|
void append(const char* data, ByteCount count) { m_data.append(data, (size_t)(int)count); }
|
||||||
|
|
||||||
|
void push_back(char c) { m_data.push_back(c); }
|
||||||
|
void resize(ByteCount size) { m_data.resize((size_t)(int)size); }
|
||||||
|
void reserve(ByteCount size) { m_data.reserve((size_t)(int)size); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Content m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringView
|
class StringView : public StringOps<StringView, const char>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr StringView() : m_data{nullptr}, m_length{0} {}
|
constexpr StringView() : m_data{nullptr}, m_length{0} {}
|
||||||
|
@ -71,50 +148,17 @@ public:
|
||||||
: m_data{data}, m_length{length} {}
|
: m_data{data}, m_length{length} {}
|
||||||
constexpr StringView(const char* data) : m_data{data}, m_length{strlen(data)} {}
|
constexpr StringView(const char* data) : m_data{data}, m_length{strlen(data)} {}
|
||||||
constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {}
|
constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {}
|
||||||
template<typename Char, typename Traits, typename Alloc>
|
StringView(const String& str) : m_data{str.data()}, m_length{(int)str.length()} {}
|
||||||
StringView(const std::basic_string<Char, Traits, Alloc>& str) : m_data{str.data()}, m_length{(int)str.length()} {}
|
|
||||||
StringView(const char& c) : m_data(&c), m_length(1) {}
|
StringView(const char& c) : m_data(&c), m_length(1) {}
|
||||||
|
|
||||||
friend bool operator==(StringView lhs, StringView rhs);
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
const char* data() const { return m_data; }
|
const char* data() const { return m_data; }
|
||||||
|
|
||||||
using iterator = const char*;
|
|
||||||
using reverse_iterator = std::reverse_iterator<const char*>;
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
|
||||||
iterator begin() const { return m_data; }
|
|
||||||
[[gnu::always_inline]]
|
|
||||||
iterator end() const { return m_data + (int)m_length; }
|
|
||||||
|
|
||||||
reverse_iterator rbegin() const { return reverse_iterator{m_data + (int)m_length}; }
|
|
||||||
reverse_iterator rend() const { return reverse_iterator{m_data}; }
|
|
||||||
|
|
||||||
char front() const { return *m_data; }
|
|
||||||
char back() const { return m_data[(int)m_length - 1]; }
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
|
||||||
char operator[](ByteCount pos) const { return m_data[(int)pos]; }
|
|
||||||
Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
ByteCount length() const { return m_length; }
|
ByteCount length() const { return m_length; }
|
||||||
CharCount char_length() const { return utf8::distance(begin(), end()); }
|
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
|
||||||
bool empty() { return m_length == 0_byte; }
|
|
||||||
|
|
||||||
ByteCount byte_count_to(CharCount count) const;
|
|
||||||
CharCount char_count_to(ByteCount count) const;
|
|
||||||
|
|
||||||
StringView substr(ByteCount from, ByteCount length = INT_MAX) const;
|
|
||||||
StringView substr(CharCount from, CharCount length = INT_MAX) const;
|
|
||||||
|
|
||||||
String str() const { return String{begin(), end()}; }
|
String str() const { return String{begin(), end()}; }
|
||||||
|
|
||||||
operator String() const { return str(); } // to remove
|
|
||||||
|
|
||||||
struct ZeroTerminatedString
|
struct ZeroTerminatedString
|
||||||
{
|
{
|
||||||
ZeroTerminatedString(const char* begin, const char* end)
|
ZeroTerminatedString(const char* begin, const char* end)
|
||||||
|
@ -122,53 +166,37 @@ public:
|
||||||
if (*end == '\0')
|
if (*end == '\0')
|
||||||
unowned = begin;
|
unowned = begin;
|
||||||
else
|
else
|
||||||
owned = StringBase(begin, end);
|
owned = String::Content(begin, end);
|
||||||
}
|
}
|
||||||
operator const char*() const { return unowned ? unowned : owned.c_str(); }
|
operator const char*() const { return unowned ? unowned : owned.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringBase owned;
|
String::Content owned;
|
||||||
const char* unowned = nullptr;
|
const char* unowned = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
ZeroTerminatedString zstr() const { return ZeroTerminatedString{begin(), end()}; }
|
ZeroTerminatedString zstr() const { return ZeroTerminatedString{begin(), end()}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr ByteCount strlen(const char* s)
|
||||||
|
{
|
||||||
|
return *s == 0 ? 0 : strlen(s+1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
const char* m_data;
|
const char* m_data;
|
||||||
ByteCount m_length;
|
ByteCount m_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(StringView lhs, StringView rhs)
|
template<typename Type, typename CharType>
|
||||||
{
|
inline StringView StringOps<Type, CharType>::substr(ByteCount from, ByteCount length) const
|
||||||
return lhs.m_length == rhs.m_length and
|
|
||||||
std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!=(StringView lhs, StringView rhs)
|
|
||||||
{
|
|
||||||
return not (lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(StringView lhs, StringView rhs);
|
|
||||||
|
|
||||||
inline ByteCount StringView::byte_count_to(CharCount count) const
|
|
||||||
{
|
|
||||||
return utf8::advance(begin(), end(), (int)count) - begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline CharCount StringView::char_count_to(ByteCount count) const
|
|
||||||
{
|
|
||||||
return utf8::distance(begin(), begin() + (int)count);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline StringView StringView::substr(ByteCount from, ByteCount length) const
|
|
||||||
{
|
{
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = INT_MAX;
|
length = INT_MAX;
|
||||||
return StringView{ m_data + (int)from, std::min(m_length - from, length) };
|
return StringView{ type().data() + (int)from, std::min(type().length() - from, length) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringView StringView::substr(CharCount from, CharCount length) const
|
template<typename Type, typename CharType>
|
||||||
|
inline StringView StringOps<Type, CharType>::substr(CharCount from, CharCount length) const
|
||||||
{
|
{
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = INT_MAX;
|
length = INT_MAX;
|
||||||
|
@ -176,70 +204,21 @@ inline StringView StringView::substr(CharCount from, CharCount length) const
|
||||||
return StringView{ beg, utf8::advance(beg, end(), length) };
|
return StringView{ beg, utf8::advance(beg, end(), length) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringView String::substr(ByteCount pos, ByteCount length) const
|
|
||||||
{
|
|
||||||
return StringView{*this}.substr(pos, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline StringView String::substr(CharCount pos, CharCount length) const
|
|
||||||
{
|
|
||||||
return StringView{*this}.substr(pos, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String& operator+=(String& lhs, StringView rhs)
|
inline String& operator+=(String& lhs, StringView rhs)
|
||||||
{
|
{
|
||||||
lhs.append(rhs.data(), (size_t)(int)rhs.length());
|
lhs.append(rhs.data(), rhs.length());
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String operator+(const String& lhs, const String& rhs)
|
|
||||||
{
|
|
||||||
String res = lhs;
|
|
||||||
res += rhs;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String operator+(StringView lhs, StringView rhs)
|
inline String operator+(StringView lhs, StringView rhs)
|
||||||
{
|
{
|
||||||
String res{lhs.begin(), lhs.end()};
|
String res;
|
||||||
|
res.reserve((int)(lhs.length() + rhs.length()));
|
||||||
|
res += lhs;
|
||||||
res += rhs;
|
res += rhs;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String operator+(const String& lhs, StringView rhs)
|
|
||||||
{
|
|
||||||
String res = lhs;
|
|
||||||
res += rhs;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String operator+(StringView lhs, const String& rhs)
|
|
||||||
{
|
|
||||||
String res{lhs.begin(), lhs.end()};
|
|
||||||
res.append(rhs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String operator+(const char* lhs, StringView rhs)
|
|
||||||
{
|
|
||||||
return StringView{lhs} + rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String operator+(StringView lhs, const char* rhs)
|
|
||||||
{
|
|
||||||
return lhs + StringView{rhs};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String operator+(const char* lhs, const String& rhs)
|
|
||||||
{
|
|
||||||
return StringView{lhs} + rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String operator+(const String& lhs, const char* rhs)
|
|
||||||
{
|
|
||||||
return lhs + StringView{rhs};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<String> split(StringView str, char separator, char escape);
|
Vector<String> split(StringView str, char separator, char escape);
|
||||||
Vector<StringView> split(StringView str, char separator);
|
Vector<StringView> split(StringView str, char separator);
|
||||||
|
|
||||||
|
@ -266,16 +245,11 @@ inline String operator"" _str(const char* str, size_t)
|
||||||
return String(str);
|
return String(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringView operator"" _sv(const char* str, size_t len)
|
|
||||||
{
|
|
||||||
return StringView(str, (int)len);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline String codepoint_to_str(Codepoint cp)
|
inline String codepoint_to_str(Codepoint cp)
|
||||||
{
|
{
|
||||||
StringBase str;
|
String str;
|
||||||
utf8::dump(back_inserter(str), cp);
|
utf8::dump(std::back_inserter(str), cp);
|
||||||
return String(str);
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_to_int(StringView str);
|
int str_to_int(StringView str);
|
||||||
|
@ -301,16 +275,6 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0);
|
||||||
|
|
||||||
Vector<StringView> wrap_lines(StringView text, CharCount max_width);
|
Vector<StringView> wrap_lines(StringView text, CharCount max_width);
|
||||||
|
|
||||||
inline size_t hash_value(const Kakoune::String& str)
|
|
||||||
{
|
|
||||||
return hash_data(str.data(), (int)str.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t hash_value(const Kakoune::StringView& str)
|
|
||||||
{
|
|
||||||
return hash_data(str.data(), (int)str.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // string_hh_INCLUDED
|
#endif // string_hh_INCLUDED
|
||||||
|
|
Loading…
Reference in New Issue
Block a user