Merge branch 'mawww:master' into master
This commit is contained in:
commit
0cf5105df1
53
colors/black-on-white.kak
Normal file
53
colors/black-on-white.kak
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Black-on-bright-white colorscheme for minimal distraction & maximal contrast.
|
||||
# Works well with e-ink screens.
|
||||
|
||||
# For Code
|
||||
face global value black
|
||||
face global type black
|
||||
face global variable black
|
||||
face global module black
|
||||
face global function black
|
||||
face global string black
|
||||
face global keyword black
|
||||
face global operator black
|
||||
face global attribute black
|
||||
face global comment black
|
||||
face global documentation comment
|
||||
face global meta black
|
||||
face global builtin black
|
||||
|
||||
# For markup
|
||||
face global title black
|
||||
face global header black
|
||||
face global mono black
|
||||
face global block black
|
||||
face global link black
|
||||
face global bullet black
|
||||
face global list black
|
||||
|
||||
# builtin faces
|
||||
face global Default black,bright-white
|
||||
face global PrimarySelection black,rgb:cccccc+fg
|
||||
face global SecondarySelection black,rgb:e0e0e0+fg
|
||||
face global PrimaryCursor bright-white,black+fg
|
||||
face global SecondaryCursor bright-white,rgb:777777+fg
|
||||
face global PrimaryCursorEol black,rgb:777777+fg
|
||||
face global SecondaryCursorEol black,rgb:aaaaaa+fg
|
||||
face global LineNumbers black,bright-white
|
||||
face global LineNumberCursor bright-white,black
|
||||
face global MenuForeground bright-white,black+fg
|
||||
face global MenuBackground black,rgb:e0e0e0+fg
|
||||
face global MenuInfo black # Overridden by MenuForeground and MenuBackground
|
||||
face global Information black,rgb:e0e0e0
|
||||
face global Error bright-white,black
|
||||
face global DiagnosticError black
|
||||
face global DiagnosticWarning black
|
||||
face global StatusLine black,bright-white
|
||||
face global StatusLineMode black,bright-white
|
||||
face global StatusLineInfo black,bright-white
|
||||
face global StatusLineValue black,bright-white
|
||||
face global StatusCursor bright-white,black
|
||||
face global Prompt bright-white,black
|
||||
face global MatchingChar black,bright-white+b
|
||||
face global Whitespace black,bright-white+fd
|
||||
face global BufferPadding black,bright-white
|
|
@ -59,5 +59,5 @@ for examples.
|
|||
When the write end of the fifo is closed, the buffer becomes an ordinary
|
||||
<<buffers#scratch-buffers,scratch buffer>>. When the buffer is deleted,
|
||||
Kakoune closes the read end of the fifo, so any program writing to it
|
||||
will receive `SIGPIPE`. This is useful as it permits to stop the writing
|
||||
will receive `SIGPIPE`. This is useful as it permits stopping the writing
|
||||
program when the buffer is deleted.
|
||||
|
|
|
@ -417,7 +417,7 @@ The following expansions are supported (with required context _in italics_):
|
|||
_in window scope_ +
|
||||
list of coordinates and dimensions of the buffer-space
|
||||
available on the current window, in the following format:
|
||||
`<coord_x> <coord_y> <width> <height>`
|
||||
`<coord_y> <coord_x> <height> <width>`
|
||||
|
||||
Values in the above list that do not mention a context are available
|
||||
everywhere.
|
||||
|
|
|
@ -113,7 +113,7 @@ add-highlighter window/ regex //\h*(TODO:)[^\n]* 0:cyan 1:yellow,red
|
|||
|
||||
capture_id can be either the capture number, or its name if a
|
||||
named capture is used in the regex (See
|
||||
<<regex#Groups, `:doc regex Groups`>>)
|
||||
<<regex#groups, `:doc regex groups`>>)
|
||||
|
||||
*dynregex* <expression> <capture_id>:<face> ...::
|
||||
similar to regex, but expand (like a command parameter would) the
|
||||
|
|
|
@ -817,7 +817,7 @@ The following keys are recognized by this mode to help with editing
|
|||
|
||||
*<a-!>*::
|
||||
expand the typed expansions in currently entered text
|
||||
(See <<expansions#typed-expansions,`:doc expansions typed-expansions`>>)
|
||||
(See <<expansions#,`:doc expansions`>>)
|
||||
|
||||
*<a-;>*, *<a-semicolon>*::
|
||||
escape to normal mode for a single command
|
||||
|
|
|
@ -85,7 +85,7 @@ See prompt commands <<keys#prompt-commands,`:doc keys prompt-commands`>>.
|
|||
Mode entered with `<a-i>`, `<a-a>` and various combinations of `[]{}` keys.
|
||||
It aims at crafting semantic selections, often called *text-objects*.
|
||||
|
||||
See object commands <<keys#object-commands,`:doc keys object-commands`>>.
|
||||
See object commands <<keys#object-selection,`:doc keys object-selection`>>.
|
||||
|
||||
=== User mode
|
||||
|
||||
|
|
|
@ -22,5 +22,5 @@ define-command -hidden file-detection %{ evaluate-commands %sh{
|
|||
fi
|
||||
} }
|
||||
|
||||
hook global BufOpenFile .* file-detection
|
||||
hook global BufWritePost .* file-detection
|
||||
hook -group file-detection global BufOpenFile .* file-detection
|
||||
hook -group file-detection global BufWritePost .* file-detection
|
||||
|
|
|
@ -56,8 +56,8 @@ evaluate-commands %sh{
|
|||
keywords='break default func interface select case defer go map struct
|
||||
chan else goto package switch const fallthrough if range type
|
||||
continue for import return var'
|
||||
types='bool byte chan complex128 complex64 error float32 float64 int int16 int32
|
||||
int64 int8 interface intptr map rune string struct uint uint16 uint32 uint64 uint8'
|
||||
types='any bool byte chan comparable complex128 complex64 error float32 float64 int int16 int32
|
||||
int64 int8 interface intptr map rune string struct uint uint16 uint32 uint64 uint8 uintptr'
|
||||
values='false true nil iota'
|
||||
functions='append cap close complex copy delete imag len make new panic print println real recover'
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ add-highlighter shared/i3/single_string/ regex "#[0-9a-fA-F]{6}" 0:value
|
|||
|
||||
# attributes
|
||||
add-highlighter shared/i3/code/ regex "client\.(background|statusline|background|separator|statusline)" 1:attribute
|
||||
add-highlighter shared/i3/code/ regex "client\.(focused_inactive|focused|unfocused|urgent|inactive_workspace|urgent_workspace|focused_workspace|active_workspace|placeholder)" 1:attribute
|
||||
add-highlighter shared/i3/code/ regex "client\.(focused_inactive|focused_tab_title|focused|unfocused|urgent|inactive_workspace|urgent_workspace|focused_workspace|active_workspace|placeholder)" 1:attribute
|
||||
|
||||
# Commands
|
||||
# ‾‾‾‾‾‾‾‾
|
||||
|
|
|
@ -39,7 +39,7 @@ define-command autorestore-restore-buffer \
|
|||
## Replace the content of the buffer with the content of the backup file
|
||||
echo -debug Restoring file: ${newer}
|
||||
|
||||
execute-keys -draft %{ %d!cat<space>\"${newer}\"<ret>d }
|
||||
execute-keys -draft %{%d!cat<space>\"${newer}\"<ret>jd}
|
||||
|
||||
## If the backup file has to be removed, issue the command once
|
||||
## the current buffer has been saved
|
||||
|
|
|
@ -14,7 +14,8 @@ define-command format-selections -docstring "Format the selections individually"
|
|||
echo "fail 'The option ''formatcmd'' must be set'"
|
||||
fi
|
||||
}
|
||||
evaluate-commands -draft -no-hooks -save-regs '|' %{
|
||||
evaluate-commands -draft -no-hooks -save-regs 'e|' %{
|
||||
set-register e nop
|
||||
set-register '|' %{
|
||||
format_in="$(mktemp "${TMPDIR:-/tmp}"/kak-formatter.XXXXXX)"
|
||||
format_out="$(mktemp "${TMPDIR:-/tmp}"/kak-formatter.XXXXXX)"
|
||||
|
@ -24,12 +25,13 @@ define-command format-selections -docstring "Format the selections individually"
|
|||
if [ $? -eq 0 ]; then
|
||||
cat "$format_out"
|
||||
else
|
||||
printf 'eval -client %s %%{ fail formatter returned an error %s }\n' "$kak_client" "$?" | kak -p "$kak_session"
|
||||
echo "set-register e fail formatter returned an error (exit code $?)" >"$kak_command_fifo"
|
||||
cat "$format_in"
|
||||
fi
|
||||
rm -f "$format_in" "$format_out"
|
||||
}
|
||||
execute-keys '|<ret>'
|
||||
%reg{e}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ define-command -params 1.. \
|
|||
update_diff() {
|
||||
(
|
||||
cd_bufdir
|
||||
git --no-pager diff -U0 "$kak_buffile" | perl -e '
|
||||
git --no-pager diff --no-ext-diff -U0 "$kak_buffile" | perl -e '
|
||||
$flags = $ENV{"kak_timestamp"};
|
||||
foreach $line (<STDIN>) {
|
||||
if ($line =~ /@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))?/) {
|
||||
|
|
|
@ -2086,14 +2086,7 @@ const CommandDesc execute_keys_cmd = {
|
|||
ScopedSetBool disable_keymaps(context.keymaps_disabled(), not parser.get_switch("with-maps"));
|
||||
ScopedSetBool disable_hoooks(context.hooks_disabled(), not parser.get_switch("with-hooks"));
|
||||
|
||||
KeyList keys;
|
||||
for (auto& param : parser)
|
||||
{
|
||||
KeyList param_keys = parse_keys(param);
|
||||
keys.insert(keys.end(), param_keys.begin(), param_keys.end());
|
||||
}
|
||||
|
||||
for (auto& key : keys)
|
||||
for (auto& key : parser | transform(parse_keys) | flatten())
|
||||
context.input_handler().handle_key(key);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ struct Array
|
|||
T m_data[N];
|
||||
};
|
||||
|
||||
template<typename T, typename... U> requires (std::is_same_v<T, U> and ...)
|
||||
Array(T, U...) -> Array<T, 1 + sizeof...(U)>;
|
||||
|
||||
template<typename T, size_t N, size_t... Indices>
|
||||
constexpr Array<T, N> make_array(const T (&data)[N], std::index_sequence<Indices...>)
|
||||
{
|
||||
|
|
|
@ -1694,18 +1694,11 @@ InputHandler::ScopedForceNormal::~ScopedForceNormal()
|
|||
if (not m_mode)
|
||||
return;
|
||||
|
||||
kak_assert(m_handler.m_mode_stack.size() > 1);
|
||||
|
||||
if (m_mode == m_handler.m_mode_stack.back().get())
|
||||
m_handler.pop_mode(m_mode);
|
||||
else
|
||||
{
|
||||
auto it = find_if(m_handler.m_mode_stack,
|
||||
[this](const RefPtr<InputMode>& m)
|
||||
{ return m.get() == m_mode; });
|
||||
kak_assert(it != m_handler.m_mode_stack.end());
|
||||
else if (auto it = find(m_handler.m_mode_stack, m_mode);
|
||||
it != m_handler.m_mode_stack.end())
|
||||
m_handler.m_mode_stack.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_valid(Key key)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "normal.hh"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "buffer.hh"
|
||||
#include "buffer_manager.hh"
|
||||
#include "buffer_utils.hh"
|
||||
|
@ -31,8 +29,6 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
enum class SelectMode
|
||||
{
|
||||
Replace,
|
||||
|
@ -1302,7 +1298,15 @@ void select_object(Context& context, NormalParams params)
|
|||
auto obj_it = find(selectors | transform(&ObjectType::key), key).base();
|
||||
if (obj_it != std::end(selectors))
|
||||
return select_and_set_last<mode>(
|
||||
context, std::bind(obj_it->func, _1, _2, count, flags));
|
||||
context, [=](Context& context, Selection& sel) { return obj_it->func(context, sel, count, flags); });
|
||||
|
||||
static constexpr auto regex_selector = [=](StringView open, StringView close, int count) {
|
||||
return [open=Regex{open, RegexCompileFlags::Backward},
|
||||
close=Regex{close, RegexCompileFlags::Backward},
|
||||
count](Context& context, Selection& sel) {
|
||||
return select_surrounding(context, sel, open, close, count, flags);
|
||||
};
|
||||
};
|
||||
|
||||
if (key == 'c')
|
||||
{
|
||||
|
@ -1323,17 +1327,13 @@ void select_object(Context& context, NormalParams params)
|
|||
|
||||
struct error : runtime_error { error(size_t) : runtime_error{"desc parsing failed, expected <open>,<close>"} {} };
|
||||
|
||||
auto params = cmdline | split<StringView>(',', '\\') |
|
||||
transform(unescape<',', '\\'>) | static_gather<error, 2>();
|
||||
|
||||
auto params = cmdline | split<StringView>(',', '\\')
|
||||
| transform(unescape<',', '\\'>)
|
||||
| static_gather<error, 2>();
|
||||
if (params[0].empty() or params[1].empty())
|
||||
throw error{0};
|
||||
|
||||
select_and_set_last<mode>(
|
||||
context, std::bind(select_surrounding, _1, _2,
|
||||
Regex{params[0], RegexCompileFlags::Backward},
|
||||
Regex{params[1], RegexCompileFlags::Backward},
|
||||
count, flags));
|
||||
select_and_set_last<mode>(context, regex_selector(params[0], params[1], count));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -1350,10 +1350,10 @@ void select_object(Context& context, NormalParams params)
|
|||
return;
|
||||
}
|
||||
|
||||
static constexpr struct SurroundingPair
|
||||
static constexpr struct
|
||||
{
|
||||
char opening;
|
||||
char closing;
|
||||
char open;
|
||||
char close;
|
||||
char name;
|
||||
} surrounding_pairs[] = {
|
||||
{ '(', ')', 'b' },
|
||||
|
@ -1364,28 +1364,15 @@ void select_object(Context& context, NormalParams params)
|
|||
{ '\'', '\'', 'q' },
|
||||
{ '`', '`', 'g' },
|
||||
};
|
||||
auto pair_it = find_if(surrounding_pairs,
|
||||
[key](const SurroundingPair& s) {
|
||||
return key == s.opening or key == s.closing or
|
||||
(s.name != 0 and key == s.name);
|
||||
});
|
||||
if (pair_it != std::end(surrounding_pairs))
|
||||
if (auto it = find_if(surrounding_pairs, [key](auto s) { return key == s.open or key == s.close or key == s.name; });
|
||||
it != std::end(surrounding_pairs))
|
||||
return select_and_set_last<mode>(
|
||||
context, std::bind(select_surrounding, _1, _2,
|
||||
Regex{format("\\Q{}", pair_it->opening), RegexCompileFlags::Backward},
|
||||
Regex{format("\\Q{}", pair_it->closing), RegexCompileFlags::Backward},
|
||||
count, flags));
|
||||
context, regex_selector(format("\\Q{}", it->open), format("\\Q{}", it->close), count));
|
||||
|
||||
if (not key.codepoint())
|
||||
return;
|
||||
|
||||
const Codepoint cp = *key.codepoint();
|
||||
if (is_punctuation(cp, {}))
|
||||
if (auto cp = key.codepoint(); cp and is_punctuation(*cp, {}))
|
||||
{
|
||||
auto re = Regex{"\\Q" + to_string(cp), RegexCompileFlags::Backward};
|
||||
return select_and_set_last<mode>(
|
||||
context, std::bind(select_surrounding, _1, _2,
|
||||
re, re, count, flags));
|
||||
auto re = "\\Q" + to_string(*cp);
|
||||
return select_and_set_last<mode>(context, regex_selector(re, re, count));
|
||||
}
|
||||
}, get_title(),
|
||||
build_autoinfo_for_mapping(context, KeymapMode::Object,
|
||||
|
@ -1537,11 +1524,10 @@ void select_to_next_char(Context& context, NormalParams params)
|
|||
constexpr auto new_flags = flags & SelectFlags::Extend ? SelectMode::Extend
|
||||
: SelectMode::Replace;
|
||||
select_and_set_last<new_flags>(
|
||||
context,
|
||||
std::bind(flags & SelectFlags::Reverse ? select_to_reverse
|
||||
: select_to,
|
||||
_1, _2, *cp, params.count,
|
||||
flags & SelectFlags::Inclusive));
|
||||
context, [cp=*cp, count=params.count] (auto& context, auto& sel) {
|
||||
auto& func = flags & SelectFlags::Reverse ? select_to_reverse : select_to;
|
||||
return func(context, sel, cp, count, flags & SelectFlags::Inclusive);
|
||||
});
|
||||
}, get_title(), "enter char to select to");
|
||||
}
|
||||
|
||||
|
|
|
@ -7,24 +7,29 @@ namespace Kakoune
|
|||
{
|
||||
|
||||
UnitTest test_ranges{[] {
|
||||
auto check_equal = [](auto&& container, ConstArrayView<StringView> expected) {
|
||||
using Strs = ConstArrayView<StringView>;
|
||||
auto check_equal = [](auto&& container, auto&& expected) {
|
||||
kak_assert(std::equal(container.begin(), container.end(), expected.begin(), expected.end()));
|
||||
};
|
||||
check_equal("a,b,c"_sv | split<StringView>(','), {"a", "b", "c"});
|
||||
check_equal(",b,c"_sv | split<StringView>(','), {"", "b", "c"});
|
||||
check_equal(",b,"_sv | split<StringView>(','), {"", "b", ""});
|
||||
check_equal(","_sv | split<StringView>(','), {"", ""});
|
||||
check_equal(""_sv | split<StringView>(','), {});
|
||||
check_equal("a,b,c"_sv | split<StringView>(','), Strs{"a", "b", "c"});
|
||||
check_equal(",b,c"_sv | split<StringView>(','), Strs{"", "b", "c"});
|
||||
check_equal(",b,"_sv | split<StringView>(','), Strs{"", "b", ""});
|
||||
check_equal(","_sv | split<StringView>(','), Strs{"", ""});
|
||||
check_equal(""_sv | split<StringView>(','), Strs{});
|
||||
|
||||
check_equal("a,b,c,"_sv | split_after<StringView>(','), {"a,", "b,", "c,"});
|
||||
check_equal("a,b,c"_sv | split_after<StringView>(','), {"a,", "b,", "c"});
|
||||
check_equal("a,b,c,"_sv | split_after<StringView>(','), Strs{"a,", "b,", "c,"});
|
||||
check_equal("a,b,c"_sv | split_after<StringView>(','), Strs{"a,", "b,", "c"});
|
||||
|
||||
check_equal(R"(a\,,\,b,\,)"_sv | split<StringView>(',', '\\')
|
||||
| transform(unescape<',', '\\'>), {"a,", ",b", ","});
|
||||
| transform(unescape<',', '\\'>), Strs{"a,", ",b", ","});
|
||||
check_equal(R"(\,\,)"_sv | split<StringView>(',', '\\')
|
||||
| transform(unescape<',', '\\'>), {",,"});
|
||||
| transform(unescape<',', '\\'>), Strs{",,"});
|
||||
check_equal(R"(\\,\\,)"_sv | split<StringView>(',', '\\')
|
||||
| transform(unescape<',', '\\'>), {R"(\)", R"(\)", ""});
|
||||
| transform(unescape<',', '\\'>), Strs{R"(\)", R"(\)", ""});
|
||||
|
||||
check_equal(Array{""_sv, "abc"_sv, ""_sv, "def"_sv, ""_sv} | flatten(), "abcdef"_sv);
|
||||
check_equal(Vector<StringView>{"", ""} | flatten(), ""_sv);
|
||||
check_equal(Vector<StringView>{} | flatten(), ""_sv);
|
||||
}};
|
||||
|
||||
}
|
||||
|
|
132
src/ranges.hh
132
src/ranges.hh
|
@ -24,13 +24,33 @@ decltype(auto) operator| (Range&& range, ViewFactory<Func> factory)
|
|||
}
|
||||
|
||||
template<typename Range>
|
||||
struct decay_range_impl { using type = std::remove_cvref_t<Range>; };
|
||||
struct DecayRangeImpl { using type = std::remove_cvref_t<Range>; };
|
||||
|
||||
template<typename Range>
|
||||
struct decay_range_impl<Range&> { using type = Range&; };
|
||||
struct DecayRangeImpl<Range&> { using type = Range&; };
|
||||
|
||||
template<typename Range>
|
||||
using decay_range = typename decay_range_impl<Range>::type;
|
||||
using DecayRange = typename DecayRangeImpl<Range>::type;
|
||||
|
||||
template<typename Range>
|
||||
struct RangeHolderImpl { using type = std::remove_cvref_t<Range>; };
|
||||
|
||||
template<typename Range>
|
||||
struct RangeHolderImpl<Range&> {
|
||||
struct type
|
||||
{
|
||||
Range* range{};
|
||||
|
||||
decltype(auto) begin() { return std::begin(*range); }
|
||||
decltype(auto) end() { return std::end(*range); }
|
||||
|
||||
type& operator=(Range& r) { range = &r; return *this; }
|
||||
operator Range&() { return *range; }
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Range>
|
||||
using RangeHolder = typename RangeHolderImpl<Range>::type;
|
||||
|
||||
template<typename Range>
|
||||
struct ReverseView
|
||||
|
@ -47,11 +67,11 @@ struct ReverseView
|
|||
Range m_range;
|
||||
};
|
||||
|
||||
inline auto reverse()
|
||||
constexpr auto reverse()
|
||||
{
|
||||
return ViewFactory{[](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return ReverseView<decay_range<Range>>{std::forward<Range>(range)};
|
||||
return ReverseView<DecayRange<Range>>{std::forward<Range>(range)};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -71,11 +91,11 @@ struct SkipView
|
|||
size_t m_skip_count;
|
||||
};
|
||||
|
||||
inline auto skip(size_t count)
|
||||
constexpr auto skip(size_t count)
|
||||
{
|
||||
return ViewFactory{[count](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return SkipView<decay_range<Range>>{std::forward<Range>(range), count};
|
||||
return SkipView<DecayRange<Range>>{std::forward<Range>(range), count};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -89,11 +109,11 @@ struct DropView
|
|||
size_t m_drop_count;
|
||||
};
|
||||
|
||||
inline auto drop(size_t count)
|
||||
constexpr auto drop(size_t count)
|
||||
{
|
||||
return ViewFactory{[count](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return DropView<decay_range<Range>>{std::forward<Range>(range), count};
|
||||
return DropView<DecayRange<Range>>{std::forward<Range>(range), count};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -147,11 +167,11 @@ struct FilterView
|
|||
};
|
||||
|
||||
template<typename Filter>
|
||||
inline auto filter(Filter f)
|
||||
constexpr auto filter(Filter f)
|
||||
{
|
||||
return ViewFactory{[f = std::move(f)](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return FilterView<decay_range<Range>, Filter>{std::forward<Range>(range), std::move(f)};
|
||||
return FilterView<DecayRange<Range>, Filter>{std::forward<Range>(range), std::move(f)};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -193,11 +213,11 @@ struct EnumerateView
|
|||
Range m_range;
|
||||
};
|
||||
|
||||
inline auto enumerate()
|
||||
constexpr auto enumerate()
|
||||
{
|
||||
return ViewFactory{[](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return EnumerateView<decay_range<Range>>{std::forward<Range>(range)};
|
||||
return EnumerateView<DecayRange<Range>>{std::forward<Range>(range)};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -252,11 +272,11 @@ struct TransformView
|
|||
};
|
||||
|
||||
template<typename Transform>
|
||||
inline auto transform(Transform t)
|
||||
constexpr auto transform(Transform t)
|
||||
{
|
||||
return ViewFactory{[t = std::move(t)](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return TransformView<decay_range<Range>, Transform>{std::forward<Range>(range), std::move(t)};
|
||||
return TransformView<DecayRange<Range>, Transform>{std::forward<Range>(range), std::move(t)};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -267,7 +287,7 @@ template<typename T, typename U> requires std::is_same_v<std::remove_cvref_t<dec
|
|||
struct is_pointer_like<T, U> : std::true_type {};
|
||||
|
||||
template<typename M, typename T>
|
||||
inline auto transform(M T::*member)
|
||||
constexpr auto transform(M T::*member)
|
||||
{
|
||||
return transform([member](auto&& arg) -> decltype(auto) {
|
||||
using Arg = decltype(arg);
|
||||
|
@ -364,7 +384,7 @@ auto split(Element separator)
|
|||
{
|
||||
return ViewFactory{[s = std::move(separator)](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return SplitView<decay_range<Range>, false, false, Element, ValueType>{std::forward<Range>(range), std::move(s), {}};
|
||||
return SplitView<DecayRange<Range>, false, false, Element, ValueType>{std::forward<Range>(range), std::move(s), {}};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -373,7 +393,7 @@ auto split_after(Element separator)
|
|||
{
|
||||
return ViewFactory{[s = std::move(separator)](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return SplitView<decay_range<Range>, false, true, Element, ValueType>{std::forward<Range>(range), std::move(s), {}};
|
||||
return SplitView<DecayRange<Range>, false, true, Element, ValueType>{std::forward<Range>(range), std::move(s), {}};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -382,7 +402,79 @@ auto split(Element separator, Element escaper)
|
|||
{
|
||||
return ViewFactory{[s = std::move(separator), e = std::move(escaper)](auto&& range) {
|
||||
using Range = decltype(range);
|
||||
return SplitView<decay_range<Range>, true, false, Element, ValueType>{std::forward<Range>(range), std::move(s), std::move(e)};
|
||||
return SplitView<DecayRange<Range>, true, false, Element, ValueType>{std::forward<Range>(range), std::move(s), std::move(e)};
|
||||
}};
|
||||
}
|
||||
|
||||
template<typename Range>
|
||||
struct FlattenedView
|
||||
{
|
||||
using OuterIt = IteratorOf<Range>;
|
||||
using InnerRange = ValueOf<Range>;
|
||||
using InnerIt = IteratorOf<InnerRange>;
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
using value_type = typename std::iterator_traits<InnerIt>::value_type;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::size_t;
|
||||
using reference = value_type&;
|
||||
|
||||
Iterator() = default;
|
||||
Iterator(OuterIt begin, OuterIt end) : m_outer_it{begin}, m_outer_end{end}
|
||||
{
|
||||
find_next_inner();
|
||||
}
|
||||
|
||||
decltype(auto) operator*() { return *m_inner_it; }
|
||||
|
||||
Iterator& operator++()
|
||||
{
|
||||
if (++m_inner_it == std::end(m_inner_range))
|
||||
{
|
||||
++m_outer_it;
|
||||
find_next_inner();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Iterator operator++(int) { auto copy = *this; ++*this; return copy; }
|
||||
|
||||
friend bool operator==(const Iterator& lhs, const Iterator& rhs)
|
||||
{
|
||||
return lhs.m_outer_it == rhs.m_outer_it and lhs.m_inner_it == rhs.m_inner_it;
|
||||
}
|
||||
|
||||
void find_next_inner()
|
||||
{
|
||||
m_inner_it = InnerIt{};
|
||||
for (; m_outer_it != m_outer_end; ++m_outer_it)
|
||||
{
|
||||
m_inner_range = *m_outer_it;
|
||||
if (std::begin(m_inner_range) != std::end(m_inner_range))
|
||||
{
|
||||
m_inner_it = std::begin(m_inner_range);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OuterIt m_outer_it{};
|
||||
OuterIt m_outer_end{};
|
||||
InnerIt m_inner_it{};
|
||||
RangeHolder<InnerRange> m_inner_range;
|
||||
};
|
||||
|
||||
Iterator begin() const { return {std::begin(m_range), std::end(m_range)}; }
|
||||
Iterator end() const { return {std::end(m_range), std::end(m_range)}; }
|
||||
|
||||
Range m_range;
|
||||
};
|
||||
|
||||
constexpr auto flatten()
|
||||
{
|
||||
return ViewFactory{[](auto&& range){
|
||||
using Range = decltype(range);
|
||||
return FlattenedView<DecayRange<Range>>{std::forward<Range>(range)};
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -434,7 +526,7 @@ struct ConcatView
|
|||
};
|
||||
|
||||
template<typename Range1, typename Range2>
|
||||
ConcatView<decay_range<Range1>, decay_range<Range2>> concatenated(Range1&& range1, Range2&& range2)
|
||||
ConcatView<DecayRange<Range1>, DecayRange<Range2>> concatenated(Range1&& range1, Range2&& range2)
|
||||
{
|
||||
return {range1, range2};
|
||||
}
|
||||
|
|
|
@ -88,8 +88,8 @@ struct RefPtr
|
|||
acquire();
|
||||
}
|
||||
|
||||
friend bool operator==(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr == rhs.m_ptr; }
|
||||
friend bool operator!=(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr != rhs.m_ptr; }
|
||||
friend bool operator==(const RefPtr& lhs, const RefPtr& rhs) = default;
|
||||
friend bool operator==(const RefPtr& lhs, const T* rhs) { return lhs.m_ptr == rhs; }
|
||||
|
||||
private:
|
||||
T* m_ptr = nullptr;
|
||||
|
|
|
@ -605,8 +605,8 @@ const String& session_directory()
|
|||
|
||||
String session_path(StringView session)
|
||||
{
|
||||
if (contains(session, '/'))
|
||||
throw runtime_error{"session names cannot have slashes"};
|
||||
if (not all_of(session, is_identifier))
|
||||
throw runtime_error{format("invalid session name: '{}'", session)};
|
||||
return format("{}/{}", session_directory(), session);
|
||||
}
|
||||
|
||||
|
@ -614,7 +614,10 @@ static sockaddr_un session_addr(StringView session)
|
|||
{
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, session_path(session).c_str());
|
||||
String path = session_path(session);
|
||||
if (path.length() + 1 > sizeof addr.sun_path)
|
||||
throw runtime_error{format("socket path too long: '{}'", path)};
|
||||
strcpy(addr.sun_path, path.c_str());
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
@ -848,9 +851,6 @@ private:
|
|||
Server::Server(String session_name, bool is_daemon)
|
||||
: m_session{std::move(session_name)}, m_is_daemon{is_daemon}
|
||||
{
|
||||
if (not all_of(m_session, is_identifier))
|
||||
throw runtime_error{format("invalid session name: '{}'", m_session)};
|
||||
|
||||
int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
fcntl(listen_sock, F_SETFD, FD_CLOEXEC);
|
||||
sockaddr_un addr = session_addr(m_session);
|
||||
|
@ -885,9 +885,6 @@ Server::Server(String session_name, bool is_daemon)
|
|||
|
||||
bool Server::rename_session(StringView name)
|
||||
{
|
||||
if (not all_of(name, is_identifier))
|
||||
throw runtime_error{format("invalid session name: '{}'", name)};
|
||||
|
||||
String old_socket_file = session_path(m_session);
|
||||
String new_socket_file = session_path(name);
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
i<a-;>,d<esc>
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
edit -scratch
|
||||
map global user d :delete-buffer<ret>
|
Loading…
Reference in New Issue
Block a user