1
1
mirror of https://github.com/mawww/kakoune.git synced 2024-09-11 13:00:41 +03:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Bruno Heridet
6e18812c2c
Merge 4dd9dbb3f8 into 238e5e7659 2024-08-13 22:17:11 +02:00
Maxime Coste
238e5e7659 Try to make tests less timing sensitive 2024-08-13 20:39:44 +10:00
Maxime Coste
560e3631ec Move debug utils to debug.hh/debug.cc
Lots of code includes buffer_utils.hh just for write_to_debug_buffer
which pulls many unnecessary dependencies. Reorganise to reduce
compile times.
2024-08-12 20:02:11 +10:00
Maxime Coste
6ed01f402b Reduce headers dependency graph
Move more code into the implementation files to reduce the amount
of code pulled by headers.
2024-08-12 20:02:11 +10:00
Maxime Coste
1b2100753e Reduce exposed headers from context.hh 2024-08-12 20:02:11 +10:00
Maxime Coste
1a52006c3d Extract format implementation to its own file
Split it to avoid pulling all string_utils dependencies for just
format.
2024-08-12 20:02:11 +10:00
Maxime Coste
2d9886afe7 Remove void_t and use requires instead 2024-08-12 20:02:11 +10:00
Maxime Coste
a250b96c18 Move most info/status clear logic to client
This makes it possible to remove the pending clears whenever an
info/status line is explicitely added, removing a class of race
conditions introduced by the previous implementation.
2024-08-12 17:10:12 +10:00
Delapouite
4dd9dbb3f8 Display recorded keys during macro recording 2018-06-03 12:55:43 +02:00
63 changed files with 573 additions and 426 deletions

View File

@ -3,6 +3,7 @@
#include "safe_ptr.hh"
#include "string.hh"
#include "ranges.hh"
#include "hash_map.hh"
namespace Kakoune

View File

@ -1,8 +1,10 @@
#include "assert.hh"
#include "backtrace.hh"
#include "buffer_utils.hh"
#include "format.hh"
#include "file.hh"
#include "exception.hh"
#include "debug.hh"
#include <sys/types.h>
#include <unistd.h>

View File

@ -1,7 +1,7 @@
#include "backtrace.hh"
#include "string.hh"
#include "string_utils.hh"
#include "format.hh"
#if defined(__GLIBC__) || defined(__APPLE__)
# include <execinfo.h>

View File

@ -271,36 +271,6 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, bool scroll
return buffer;
}
void write_to_debug_buffer(StringView str)
{
if (not BufferManager::has_instance())
{
write(2, str);
write(2, "\n");
return;
}
constexpr StringView debug_buffer_name = "*debug*";
// Try to ensure we keep an empty line at the end of the debug buffer
// where the user can put its cursor to scroll with new messages
const bool eol_back = not str.empty() and str.back() == '\n';
if (Buffer* buffer = BufferManager::instance().get_buffer_ifp(debug_buffer_name))
{
buffer->flags() &= ~Buffer::Flags::ReadOnly;
auto restore = on_scope_end([buffer] { buffer->flags() |= Buffer::Flags::ReadOnly; });
buffer->insert(buffer->back_coord(), eol_back ? str : str + "\n");
}
else
{
String line = str + (eol_back ? "\n" : "\n\n");
create_buffer_from_string(
debug_buffer_name.str(), Buffer::Flags::NoUndo | Buffer::Flags::Debug | Buffer::Flags::ReadOnly,
line);
}
}
auto to_string(Buffer::HistoryId id)
{
using Result = decltype(to_string(size_t{}));

View File

@ -4,6 +4,7 @@
#include "context.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "file.hh"
#include "remote.hh"
#include "option.hh"
@ -130,6 +131,7 @@ void Client::print_status(DisplayLine status_line)
{
m_status_line = std::move(status_line);
m_ui_pending |= StatusLine;
m_pending_clear &= ~PendingClear::StatusLine;
}
@ -144,7 +146,8 @@ String generate_context_info(const Context& context)
if (context.buffer().is_modified())
s += "[+]";
if (context.client().input_handler().is_recording())
s += format("[recording ({})]", context.client().input_handler().recording_reg());
s += format("[recording ({}): {}]", context.client().input_handler().recording_reg(),
context.client().input_handler().recorded_keys());
if (context.hooks_disabled())
s += "[no-hooks]";
if (not(context.buffer().flags() & (Buffer::Flags::File | Buffer::Flags::Debug)))
@ -467,6 +470,7 @@ void Client::info_show(DisplayLine title, DisplayLineList content, BufferCoord a
m_info = Info{ std::move(title), std::move(content), anchor, {}, style };
m_ui_pending |= InfoShow;
m_ui_pending &= ~InfoHide;
m_pending_clear &= ~PendingClear::Info;
}
void Client::info_show(StringView title, StringView content, BufferCoord anchor, InfoStyle style)
@ -490,4 +494,21 @@ void Client::info_hide(bool even_modal)
m_ui_pending &= ~InfoShow;
}
void Client::schedule_clear()
{
if (not (m_ui_pending & InfoShow))
m_pending_clear |= PendingClear::Info;
if (not (m_ui_pending & StatusLine))
m_pending_clear |= PendingClear::StatusLine;
}
void Client::clear_pending()
{
if (m_pending_clear & PendingClear::StatusLine)
print_status({});
if (m_pending_clear & PendingClear::Info)
info_hide();
m_pending_clear = PendingClear::None;
}
}

View File

@ -56,6 +56,9 @@ public:
DisplayCoord dimensions() const;
void schedule_clear();
void clear_pending();
void force_redraw(bool full = false);
void redraw_ifn();
@ -111,6 +114,16 @@ private:
};
int m_ui_pending = 0;
enum class PendingClear
{
None = 0,
Info = 0b01,
StatusLine = 0b10
};
friend constexpr bool with_bit_ops(Meta::Type<PendingClear>) { return true; }
PendingClear m_pending_clear = PendingClear::None;
struct Menu
{
Vector<DisplayLine> items;

View File

@ -2,7 +2,7 @@
#include "exception.hh"
#include "ranges.hh"
#include "string_utils.hh"
#include "format.hh"
#include <cstdio>

View File

@ -2,10 +2,11 @@
#include "alias_registry.hh"
#include "assert.hh"
#include "buffer_utils.hh"
#include "context.hh"
#include "debug.hh"
#include "flags.hh"
#include "file.hh"
#include "hook_manager.hh"
#include "optional.hh"
#include "option_types.hh"
#include "profile.hh"
@ -13,6 +14,7 @@
#include "regex.hh"
#include "register_manager.hh"
#include "shell_manager.hh"
#include "scope.hh"
#include "utils.hh"
#include "unit_tests.hh"

View File

@ -8,6 +8,7 @@
#include "command_manager.hh"
#include "completion.hh"
#include "context.hh"
#include "debug.hh"
#include "event_manager.hh"
#include "face_registry.hh"
#include "file.hh"

View File

@ -2,6 +2,7 @@
#include "file.hh"
#include "context.hh"
#include "option_types.hh"
#include "option_manager.hh"
#include "regex.hh"
namespace Kakoune

View File

@ -1,10 +1,8 @@
#include "context.hh"
#include "alias_registry.hh"
#include "client.hh"
#include "face_registry.hh"
#include "scope.hh"
#include "buffer_manager.hh"
#include "hook_manager.hh"
#include "register_manager.hh"
#include "window.hh"
@ -62,6 +60,12 @@ Scope& Context::scope(bool allow_local) const
return GlobalScope::instance();
}
OptionManager& Context::options() const { return scope().options(); }
HookManager& Context::hooks() const { return scope().hooks(); }
KeymapManager& Context::keymaps() const { return scope().keymaps(); }
AliasRegistry& Context::aliases() const { return scope().aliases(); }
FaceRegistry& Context::faces(bool allow_local) const { return scope(allow_local).faces(); }
void Context::set_client(Client& client)
{
kak_assert(not has_client());
@ -82,6 +86,12 @@ void Context::print_status(DisplayLine status) const
client().print_status(std::move(status));
}
void Context::push_jump(bool force)
{
if (force or not (m_flags & Flags::Draft))
m_jump_list.push(selections());
}
void JumpList::push(SelectionList jump, Optional<size_t> index)
{
if (index)
@ -428,4 +438,22 @@ void Context::set_name(String name) {
String old_name = std::exchange(m_name, std::move(name));
hooks().run_hook(Hook::ClientRenamed, format("{}:{}", old_name, m_name), *this);
}
ScopedEdition::ScopedEdition(Context& context)
: m_context{context},
m_buffer{context.has_buffer() ? &context.buffer() : nullptr}
{ if (m_buffer) m_context.begin_edition(); }
ScopedEdition::~ScopedEdition() { if (m_buffer) m_context.end_edition(); }
ScopedSelectionEdition::ScopedSelectionEdition(Context& context)
: m_context{context},
m_buffer{not (m_context.flags() & Context::Flags::Draft) and context.has_buffer() ? &context.buffer() : nullptr}
{ if (m_buffer) m_context.m_selection_history.begin_edition(); }
ScopedSelectionEdition::ScopedSelectionEdition(ScopedSelectionEdition&& other) : m_context{other.m_context}, m_buffer{other.m_buffer}
{ other.m_buffer = nullptr; }
ScopedSelectionEdition::~ScopedSelectionEdition() { if (m_buffer) m_context.m_selection_history.end_edition(); }
}

View File

@ -4,20 +4,26 @@
#include "selection.hh"
#include "optional.hh"
#include "utils.hh"
#include "flags.hh"
#include <functional>
namespace Kakoune
{
class Context;
class Window;
class Buffer;
class Client;
class Scope;
class InputHandler;
class DisplayLine;
class KeymapManager;
class AliasRegistry;
class FaceRegistry;
class OptionManager;
class KeymapManager;
class HookManager;
enum Direction { Backward = -1, Forward = 1 };
@ -104,11 +110,11 @@ public:
Scope& scope(bool allow_local = true) const;
Scope* local_scope() const { return m_local_scopes.empty() ? nullptr : m_local_scopes.back(); }
OptionManager& options() const { return scope().options(); }
HookManager& hooks() const { return scope().hooks(); }
KeymapManager& keymaps() const { return scope().keymaps(); }
AliasRegistry& aliases() const { return scope().aliases(); }
FaceRegistry& faces(bool allow_local = true) const { return scope(allow_local).faces(); }
OptionManager& options() const;
HookManager& hooks() const;
KeymapManager& keymaps() const;
AliasRegistry& aliases() const;
FaceRegistry& faces(bool allow_local = true) const;
void print_status(DisplayLine status) const;
@ -132,11 +138,7 @@ public:
Flags flags() const { return m_flags; }
JumpList& jump_list() { return m_jump_list; }
void push_jump(bool force = false)
{
if (force or not (m_flags & Flags::Draft))
m_jump_list.push(selections());
}
void push_jump(bool force = false);
template<typename Func>
void set_last_select(Func&& last_select) { m_last_select = std::forward<Func>(last_select); }
@ -215,12 +217,9 @@ private:
struct ScopedEdition
{
ScopedEdition(Context& context)
: m_context{context},
m_buffer{context.has_buffer() ? &context.buffer() : nullptr}
{ if (m_buffer) m_context.begin_edition(); }
~ScopedEdition() { if (m_buffer) m_context.end_edition(); }
ScopedEdition(Context& context);
~ScopedEdition();
ScopedEdition(const ScopedEdition&) = delete;
Context& context() const { return m_context; }
private:
@ -230,14 +229,10 @@ private:
struct ScopedSelectionEdition
{
ScopedSelectionEdition(Context& context)
: m_context{context},
m_buffer{not (m_context.flags() & Context::Flags::Draft) and context.has_buffer() ? &context.buffer() : nullptr}
{ if (m_buffer) m_context.m_selection_history.begin_edition(); }
ScopedSelectionEdition(ScopedSelectionEdition&& other) : m_context{other.m_context}, m_buffer{other.m_buffer}
{ other.m_buffer = nullptr; }
ScopedSelectionEdition(Context& context);
ScopedSelectionEdition(ScopedSelectionEdition&& other);
~ScopedSelectionEdition();
~ScopedSelectionEdition() { if (m_buffer) m_context.m_selection_history.end_edition(); }
private:
Context& m_context;
SafePtr<Buffer> m_buffer;

39
src/debug.cc Normal file
View File

@ -0,0 +1,39 @@
#include "debug.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "utils.hh"
namespace Kakoune
{
void write_to_debug_buffer(StringView str)
{
if (not BufferManager::has_instance())
{
write(2, str);
write(2, "\n");
return;
}
constexpr StringView debug_buffer_name = "*debug*";
// Try to ensure we keep an empty line at the end of the debug buffer
// where the user can put its cursor to scroll with new messages
const bool eol_back = not str.empty() and str.back() == '\n';
if (Buffer* buffer = BufferManager::instance().get_buffer_ifp(debug_buffer_name))
{
buffer->flags() &= ~Buffer::Flags::ReadOnly;
auto restore = on_scope_end([buffer] { buffer->flags() |= Buffer::Flags::ReadOnly; });
buffer->insert(buffer->back_coord(), eol_back ? str : str + "\n");
}
else
{
String line = str + (eol_back ? "\n" : "\n\n");
create_buffer_from_string(
debug_buffer_name.str(), Buffer::Flags::NoUndo | Buffer::Flags::Debug | Buffer::Flags::ReadOnly,
line);
}
}
}

40
src/debug.hh Normal file
View File

@ -0,0 +1,40 @@
#ifndef debug_hh_INCLUDED
#define debug_hh_INCLUDED
#include "constexpr_utils.hh"
#include "enum.hh"
#include "flags.hh"
namespace Kakoune
{
class StringView;
enum class DebugFlags
{
None = 0,
Hooks = 1 << 0,
Shell = 1 << 1,
Profile = 1 << 2,
Keys = 1 << 3,
Commands = 1 << 4,
};
constexpr bool with_bit_ops(Meta::Type<DebugFlags>) { return true; }
constexpr auto enum_desc(Meta::Type<DebugFlags>)
{
return make_array<EnumDesc<DebugFlags>>({
{ DebugFlags::Hooks, "hooks" },
{ DebugFlags::Shell, "shell" },
{ DebugFlags::Profile, "profile" },
{ DebugFlags::Keys, "keys" },
{ DebugFlags::Commands, "commands" },
});
}
void write_to_debug_buffer(StringView str);
}
#endif // debug_hh_INCLUDED

View File

@ -7,6 +7,8 @@
#include "string.hh"
#include "vector.hh"
#include "hash_map.hh"
#include "ranges.hh"
#include <functional>
namespace Kakoune

View File

@ -2,7 +2,7 @@
#include "exception.hh"
#include "ranges.hh"
#include "string_utils.hh"
#include "format.hh"
namespace Kakoune
{

View File

@ -6,6 +6,7 @@
#include "meta.hh"
#include "string.hh"
#include "units.hh"
#include "constexpr_utils.hh"
#include "vector.hh"
#include <sys/types.h>

180
src/format.cc Normal file
View File

@ -0,0 +1,180 @@
#include "format.hh"
#include "exception.hh"
#include "string_utils.hh"
#include <charconv>
namespace Kakoune
{
template<size_t N>
InplaceString<N> to_string_impl(auto val, auto format)
{
InplaceString<N> res;
auto [end, errc] = std::to_chars(res.m_data, res.m_data + N, val, format);
if (errc != std::errc{})
throw runtime_error("to_string error");
res.m_length = end - res.m_data;
*end = '\0';
return res;
}
template<size_t N>
InplaceString<N> to_string_impl(auto val)
{
return to_string_impl<N>(val, 10);
}
InplaceString<15> to_string(int val)
{
return to_string_impl<15>(val);
}
InplaceString<15> to_string(unsigned val)
{
return to_string_impl<15>(val);
}
InplaceString<23> to_string(long int val)
{
return to_string_impl<23>(val);
}
InplaceString<23> to_string(long long int val)
{
return to_string_impl<23>(val);
}
InplaceString<23> to_string(unsigned long val)
{
return to_string_impl<23>(val);
}
InplaceString<23> to_string(Hex val)
{
return to_string_impl<23>(val.val, 16);
}
InplaceString<23> to_string(Grouped val)
{
auto ungrouped = to_string_impl<23>(val.val);
InplaceString<23> res;
for (int pos = 0, len = ungrouped.m_length; pos != len; ++pos)
{
if (res.m_length and ((len - pos) % 3) == 0)
res.m_data[res.m_length++] = ',';
res.m_data[res.m_length++] = ungrouped.m_data[pos];
}
return res;
}
InplaceString<23> to_string(float val)
{
#if defined(__cpp_lib_to_chars)
return to_string_impl<23>(val, std::chars_format::general);
#else
InplaceString<23> res;
res.m_length = snprintf(res.m_data, 23, "%f", val);
return res;
#endif
}
InplaceString<7> to_string(Codepoint c)
{
InplaceString<7> res;
char* ptr = res.m_data;
utf8::dump(ptr, c);
res.m_length = (int)(ptr - res.m_data);
return res;
}
template<typename AppendFunc>
void format_impl(StringView fmt, ArrayView<const StringView> params, AppendFunc append)
{
int implicitIndex = 0;
for (auto it = fmt.begin(), end = fmt.end(); it != end;)
{
auto opening = std::find(it, end, '{');
if (opening == end)
{
append(StringView{it, opening});
break;
}
else if (opening != it and *(opening-1) == '\\')
{
append(StringView{it, opening-1});
append('{');
it = opening + 1;
}
else
{
append(StringView{it, opening});
auto closing = std::find(opening, end, '}');
if (closing == end)
throw runtime_error("format string error, unclosed '{'");
auto format = std::find(opening+1, closing, ':');
const int index = opening+1 == format ? implicitIndex : str_to_int({opening+1, format});
if (index >= params.size())
throw runtime_error("format string parameter index too big");
if (format != closing)
{
char padding = ' ';
if (*(++format) == '0')
{
padding = '0';
++format;
}
for (ColumnCount width = str_to_int({format, closing}), len = params[index].column_length();
width > len; --width)
append(padding);
}
append(params[index]);
implicitIndex = index+1;
it = closing+1;
}
}
}
StringView format_to(ArrayView<char> buffer, StringView fmt, ArrayView<const StringView> params)
{
char* ptr = buffer.begin();
const char* end = buffer.end();
format_impl(fmt, params, [&](StringView s) mutable {
for (auto c : s)
{
if (ptr == end)
throw runtime_error("buffer is too small");
*ptr++ = c;
}
});
if (ptr == end)
throw runtime_error("buffer is too small");
*ptr = 0;
return { buffer.begin(), ptr };
}
void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params)
{
format_impl(fmt, params, append);
}
String format(StringView fmt, ArrayView<const StringView> params)
{
ByteCount size = fmt.length();
for (auto& s : params) size += s.length();
String res;
res.reserve(size);
format_impl(fmt, params, [&](StringView s) { res += s; });
return res;
}
}

81
src/format.hh Normal file
View File

@ -0,0 +1,81 @@
#ifndef format_hh_INCLUDED
#define format_hh_INCLUDED
#include "string.hh"
#include "utils.hh"
namespace Kakoune
{
template<size_t N>
struct InplaceString
{
static_assert(N < 256, "InplaceString cannot handle sizes >= 256");
constexpr operator StringView() const { return {m_data, ByteCount{m_length}}; }
operator String() const { return {m_data, ByteCount{m_length}}; }
unsigned char m_length{};
char m_data[N];
};
struct Hex { size_t val; };
constexpr Hex hex(size_t val) { return {val}; }
struct Grouped { size_t val; };
constexpr Grouped grouped(size_t val) { return {val}; }
InplaceString<15> to_string(int val);
InplaceString<15> to_string(unsigned val);
InplaceString<23> to_string(long int val);
InplaceString<23> to_string(unsigned long val);
InplaceString<23> to_string(long long int val);
InplaceString<23> to_string(Hex val);
InplaceString<23> to_string(Grouped val);
InplaceString<23> to_string(float val);
InplaceString<7> to_string(Codepoint c);
template<typename RealType, typename ValueType>
decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val)
{
return to_string((ValueType)val);
}
namespace detail
{
template<typename T> requires std::is_convertible_v<T, StringView>
StringView format_param(const T& val) { return val; }
template<typename T> requires (not std::is_convertible_v<T, StringView>)
decltype(auto) format_param(const T& val) { return to_string(val); }
}
String format(StringView fmt, ArrayView<const StringView> params);
template<typename... Types>
String format(StringView fmt, Types&&... params)
{
return format(fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
}
StringView format_to(ArrayView<char> buffer, StringView fmt, ArrayView<const StringView> params);
template<typename... Types>
StringView format_to(ArrayView<char> buffer, StringView fmt, Types&&... params)
{
return format_to(buffer, fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
}
void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params);
template<typename... Types>
void format_with(FunctionRef<void (StringView)> append, StringView fmt, Types&&... params)
{
return format_with(append, fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
}
}
#endif // format_hh_INCLUDED

View File

@ -2,10 +2,12 @@
#include "clock.hh"
#include "string.hh"
#include "buffer_utils.hh"
#include "unit_tests.hh"
#include "format.hh"
#include "debug.hh"
#include <random>
#include <algorithm>
#include <unordered_map>
namespace Kakoune

View File

@ -1,6 +1,6 @@
#include "highlighter.hh"
#include "buffer_utils.hh"
#include "debug.hh"
namespace Kakoune
{

View File

@ -3,9 +3,9 @@
#include "coord.hh"
#include "completion.hh"
#include "display_buffer.hh"
#include "exception.hh"
#include "flags.hh"
#include "range.hh"
#include "hash_map.hh"
#include "array_view.hh"
#include "string.hh"
@ -18,6 +18,9 @@ namespace Kakoune
{
class Context;
class DisplayBuffer;
using BufferRange = Range<BufferCoord>;
enum class HighlightPass
{

View File

@ -1,7 +1,7 @@
#include "highlighter_group.hh"
#include "ranges.hh"
#include "string_utils.hh"
#include "format.hh"
namespace Kakoune
{

View File

@ -2,6 +2,7 @@
#include "assert.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "changes.hh"
#include "command_manager.hh"
#include "context.hh"

View File

@ -1,6 +1,6 @@
#include "hook_manager.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "clock.hh"
#include "command_manager.hh"
#include "context.hh"

View File

@ -6,6 +6,7 @@
#include "safe_ptr.hh"
#include "meta.hh"
#include "enum.hh"
#include "constexpr_utils.hh"
#include <memory>

View File

@ -1,7 +1,7 @@
#include "input_handler.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "command_manager.hh"
#include "client.hh"
#include "event_manager.hh"
@ -212,14 +212,6 @@ constexpr StringView register_doc =
class Normal : public InputMode
{
enum class PendingClear
{
None = 0,
Info = 0b01,
StatusLine = 0b10
};
friend constexpr bool with_bit_ops(Meta::Type<PendingClear>) { return true; }
public:
Normal(InputHandler& input_handler, bool single_command = false)
: InputMode(input_handler),
@ -228,13 +220,7 @@ public:
Timer::Callback{} : [this](Timer&) {
RefPtr<InputMode> keep_alive{this}; // hook could trigger pop_mode()
if (context().has_client())
{
if (m_pending_clear & PendingClear::StatusLine)
context().client().print_status({});
if (m_pending_clear & PendingClear::Info)
context().client().info_hide();
}
m_pending_clear = PendingClear::None;
context().client().clear_pending();
context().hooks().run_hook(Hook::NormalIdle, "", context());
}},
@ -381,8 +367,7 @@ public:
if (enabled() and not transient) // The hook might have changed mode
{
if (should_clear and context().has_client())
m_pending_clear = (context().client().info_pending() ? PendingClear::None : PendingClear::Info)
| (context().client().status_line_pending() ? PendingClear::None : PendingClear::StatusLine);
context().client().schedule_clear();
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
}
}
@ -416,7 +401,7 @@ public:
if (not (context().flags() & Context::Flags::Draft))
{
if (context().has_client())
m_pending_clear = PendingClear::Info | PendingClear::StatusLine;
context().client().schedule_clear();
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
}
}
@ -434,7 +419,6 @@ private:
Timer m_idle_timer;
Timer m_fs_check_timer;
MouseHandler m_mouse_handler;
PendingClear m_pending_clear = PendingClear::None;
enum class State { Normal, SingleCommand, PopOnEnabled };
State m_state;

View File

@ -5,6 +5,7 @@
#include "constexpr_utils.hh"
#include "context.hh"
#include "env_vars.hh"
#include "enum.hh"
#include "face.hh"
#include "normal.hh"
#include "optional.hh"
@ -99,6 +100,7 @@ public:
bool is_recording() const;
void stop_recording();
char recording_reg() const { return m_recording_reg; }
StringView recorded_keys() const { return m_recorded_keys; }
void reset_normal_mode();

View File

@ -2,6 +2,7 @@
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "client.hh"
#include "command_manager.hh"
#include "changes.hh"

View File

@ -3,6 +3,7 @@
#include "hash_map.hh"
#include "string.hh"
#include "string_utils.hh"
#include "value.hh"
namespace Kakoune

View File

@ -8,6 +8,7 @@
#include "keys.hh"
#include "ranges.hh"
#include "string_utils.hh"
#include "format.hh"
#include <cstdio>
#include <utility>

View File

@ -3,7 +3,8 @@
#include "array_view.hh"
#include "assert.hh"
#include "exception.hh"
#include "string_utils.hh"
#include "format.hh"
#include "ranges.hh"
#include <algorithm>

View File

@ -6,6 +6,7 @@
#include "unit_tests.hh"
#include "utf8_iterator.hh"
#include "utils.hh"
#include "format.hh"
#include "string_utils.hh"
namespace Kakoune

View File

@ -1,12 +1,13 @@
#include "assert.hh"
#include "backtrace.hh"
#include "buffer.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "buffer_manager.hh"
#include "client_manager.hh"
#include "command_manager.hh"
#include "commands.hh"
#include "context.hh"
#include "debug.hh"
#include "event_manager.hh"
#include "face_registry.hh"
#include "file.hh"

View File

@ -1,17 +1,12 @@
#ifndef meta_hh_INCLUDED
#define meta_hh_INCLUDED
namespace Kakoune
{
inline namespace Meta
namespace Kakoune::inline Meta
{
struct AnyType{};
template<typename T> struct Type : AnyType {};
template<typename T> using void_t = void;
}
}
#endif // meta_hh_INCLUDED

View File

@ -1841,7 +1841,7 @@ SelectionList read_selections_from_register(char reg, const Context& context)
const auto buffer_name = StringView{ content[0].begin (), end_content[1].begin () - 1 };
Buffer& buffer = BufferManager::instance().get_buffer(buffer_name);
return selection_list_from_strings(buffer, ColumnType::Byte, content | skip(1), timestamp, main);
return selection_list_from_strings(buffer, ColumnType::Byte, content.subrange(1), timestamp, main);
}
enum class CombineOp

View File

@ -64,29 +64,6 @@ struct PrefixedList
template<typename T>
using TimestampedList = PrefixedList<size_t, T>;
enum class DebugFlags
{
None = 0,
Hooks = 1 << 0,
Shell = 1 << 1,
Profile = 1 << 2,
Keys = 1 << 3,
Commands = 1 << 4,
};
constexpr bool with_bit_ops(Meta::Type<DebugFlags>) { return true; }
constexpr auto enum_desc(Meta::Type<DebugFlags>)
{
return make_array<EnumDesc<DebugFlags>>({
{ DebugFlags::Hooks, "hooks" },
{ DebugFlags::Shell, "shell" },
{ DebugFlags::Profile, "profile" },
{ DebugFlags::Keys, "keys" },
{ DebugFlags::Commands, "commands" },
});
}
}
#endif // option_hh_INCLUDED

View File

@ -8,6 +8,7 @@
#include "ranges.hh"
#include "utils.hh"
#include "vector.hh"
#include "format.hh"
#include "string_utils.hh"
#include <memory>

View File

@ -1,4 +1,5 @@
#include "option_types.hh"
#include "debug.hh"
#include "unit_tests.hh"
namespace Kakoune

View File

@ -7,9 +7,9 @@
#include "flags.hh"
#include "hash_map.hh"
#include "option.hh"
#include "ranges.hh"
#include "string.hh"
#include "string_utils.hh"
#include "format.hh"
#include "units.hh"
#include <tuple>

View File

@ -1,5 +1,6 @@
#include "parameters_parser.hh"
#include "ranges.hh"
#include "flags.hh"
namespace Kakoune

View File

@ -8,7 +8,7 @@
#include "optional.hh"
#include "flags.hh"
#include "string.hh"
#include "string_utils.hh"
#include "format.hh"
#include <functional>

View File

@ -3,6 +3,7 @@
#include "option.hh"
#include "clock.hh"
#include "option_manager.hh"
namespace Kakoune
{

View File

@ -4,6 +4,7 @@
#include "unit_tests.hh"
#include "utf8_iterator.hh"
#include "optional.hh"
#include "ranges.hh"
#include <algorithm>

View File

@ -6,9 +6,10 @@
#include "unit_tests.hh"
#include "utf8.hh"
#include "utf8_iterator.hh"
#include "string_utils.hh"
#include "format.hh"
#include "vector.hh"
#include "utils.hh"
#include "ranges.hh"
#include <cstdio>
#include <cstring>

View File

@ -9,6 +9,7 @@
#include "utils.hh"
#include <bit>
#include <algorithm>
namespace Kakoune
{
@ -210,11 +211,12 @@ constexpr bool is_direction(RegexMode mode)
(mode & ~(RegexMode::Forward | RegexMode::Backward)) == RegexMode{0};
}
template<typename It, typename=void>
template<typename It>
struct SentinelType { using Type = It; };
template<typename It>
struct SentinelType<It, void_t<typename It::Sentinel>> { using Type = typename It::Sentinel; };
requires requires { typename It::Sentinel; }
struct SentinelType<It> { using Type = typename It::Sentinel; };
template<typename Iterator, RegexMode mode>
requires (has_direction(mode))

View File

@ -3,11 +3,23 @@
#include "assert.hh"
#include "context.hh"
#include "hash_map.hh"
#include "string_utils.hh"
#include "format.hh"
#include "ranges.hh"
#include "hook_manager.hh"
namespace Kakoune
{
Register::RestoreInfo Register::save(const Context& context)
{
return get(context) | gather<RestoreInfo>();
}
void Register::restore(Context& context, const RestoreInfo& info)
{
set(context, info, true);
}
void StaticRegister::set(Context& context, ConstArrayView<String> values, bool)
{
m_content.assign(values.begin(), values.end());

View File

@ -24,8 +24,8 @@ public:
virtual const String& get_main(const Context& context, size_t main_index) = 0;
using RestoreInfo = Vector<String, MemoryDomain::Registers>;
RestoreInfo save(const Context& context) { return get(context) | gather<RestoreInfo>(); }
void restore(Context& context, const RestoreInfo& info) { set(context, info, true); }
RestoreInfo save(const Context& context);
void restore(Context& context, const RestoreInfo& info);
NestedBool& modified_hook_disabled() { return m_disable_modified_hook; }

View File

@ -1,7 +1,7 @@
#include "remote.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "client_manager.hh"
#include "command_manager.hh"
#include "display_buffer.hh"

View File

@ -7,6 +7,8 @@
namespace Kakoune
{
SelectionList::~SelectionList() = default;
SelectionList::SelectionList(Buffer& buffer, Selection s, size_t timestamp)
: m_selections({ std::move(s) }), m_buffer(&buffer), m_timestamp(timestamp)
{
@ -27,6 +29,11 @@ SelectionList::SelectionList(Buffer& buffer, Vector<Selection> list, size_t time
SelectionList::SelectionList(Buffer& buffer, Vector<Selection> list)
: SelectionList(buffer, std::move(list), buffer.timestamp()) {}
SelectionList::SelectionList(const SelectionList&) = default;
SelectionList::SelectionList(SelectionList&&) = default;
SelectionList& SelectionList::operator=(const SelectionList&) = default;
SelectionList& SelectionList::operator=(SelectionList&&) = default;
void SelectionList::remove(size_t index)
{
m_selections.erase(begin() + index);
@ -538,4 +545,31 @@ Selection selection_from_string(ColumnType column_type, const Buffer& buffer, St
return Selection{anchor, cursor};
}
SelectionList selection_list_from_strings(Buffer& buffer, ColumnType column_type, ConstArrayView<String> descs, size_t timestamp, size_t main, ColumnCount tabstop)
{
if ((column_type != ColumnType::Byte and timestamp != buffer.timestamp()) or timestamp > buffer.timestamp())
throw runtime_error{format("invalid timestamp '{}'", timestamp)};
auto from_string = [&](StringView desc) {
return selection_from_string(column_type, buffer, desc, tabstop);
};
auto sels = descs | transform(from_string) | gather<Vector<Selection>>();
if (sels.empty())
throw runtime_error{"empty selection description"};
if (main >= sels.size())
throw runtime_error{"invalid main selection index"};
sort_selections(sels, main);
merge_overlapping_selections(sels, main);
if (timestamp < buffer.timestamp())
update_selections(sels, main, buffer, timestamp);
else
clamp_selections(sels, buffer);
SelectionList res{buffer, std::move(sels)};
res.set_main_index(main);
return res;
}
}

View File

@ -1,13 +1,21 @@
#ifndef selection_hh_INCLUDED
#define selection_hh_INCLUDED
#include "buffer.hh"
#include "coord.hh"
#include "range.hh"
#include "safe_ptr.hh"
#include "utils.hh"
#include "string.hh"
#include "vector.hh"
#include <limits>
namespace Kakoune
{
class Buffer;
using BufferRange = Range<BufferCoord>;
using CaptureList = Vector<String, MemoryDomain::Selections>;
constexpr ColumnCount max_column{std::numeric_limits<int>::max()};
@ -84,11 +92,18 @@ struct SelectionList
{
static constexpr MemoryDomain Domain = MemoryDomain::Selections;
~SelectionList();
SelectionList(Buffer& buffer, Selection s);
SelectionList(Buffer& buffer, Selection s, size_t timestamp);
SelectionList(Buffer& buffer, Vector<Selection> s);
SelectionList(Buffer& buffer, Vector<Selection> s, size_t timestamp);
SelectionList(const SelectionList&);
SelectionList(SelectionList&&);
SelectionList& operator=(const SelectionList&);
SelectionList& operator=(SelectionList&&);
void update(bool merge = true);
void check_invariant() const;
@ -166,33 +181,7 @@ String selection_to_string(ColumnType column_type, const Buffer& buffer, const S
String selection_list_to_string(ColumnType column_type, const SelectionList& selections, ColumnCount tabstop = -1);
template<typename StringArray>
SelectionList selection_list_from_strings(Buffer& buffer, ColumnType column_type, StringArray&& descs, size_t timestamp, size_t main, ColumnCount tabstop = -1)
{
if ((column_type != ColumnType::Byte and timestamp != buffer.timestamp()) or timestamp > buffer.timestamp())
throw runtime_error{format("invalid timestamp '{}'", timestamp)};
auto from_string = [&](StringView desc) {
return selection_from_string(column_type, buffer, desc, tabstop);
};
auto sels = descs | transform(from_string) | gather<Vector<Selection>>();
if (sels.empty())
throw runtime_error{"empty selection description"};
if (main >= sels.size())
throw runtime_error{"invalid main selection index"};
sort_selections(sels, main);
merge_overlapping_selections(sels, main);
if (timestamp < buffer.timestamp())
update_selections(sels, main, buffer, timestamp);
else
clamp_selections(sels, buffer);
SelectionList res{buffer, std::move(sels)};
res.set_main_index(main);
return res;
}
SelectionList selection_list_from_strings(Buffer& buffer, ColumnType column_type, ConstArrayView<String> descs, size_t timestamp, size_t main, ColumnCount tabstop = -1);
}

View File

@ -6,6 +6,7 @@
#include "meta.hh"
#include "unicode.hh"
#include "vector.hh"
#include "constexpr_utils.hh"
namespace Kakoune
{

View File

@ -1,5 +1,6 @@
#include "shared_string.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "format.hh"
namespace Kakoune
{

View File

@ -1,6 +1,6 @@
#include "shell_manager.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "client.hh"
#include "clock.hh"
#include "context.hh"

View File

@ -147,88 +147,6 @@ int str_to_int(StringView str)
throw runtime_error{str + " is not a number"};
}
template<size_t N>
InplaceString<N> to_string_impl(auto val, auto format)
{
InplaceString<N> res;
auto [end, errc] = std::to_chars(res.m_data, res.m_data + N, val, format);
if (errc != std::errc{})
throw runtime_error("to_string error");
res.m_length = end - res.m_data;
*end = '\0';
return res;
}
template<size_t N>
InplaceString<N> to_string_impl(auto val)
{
return to_string_impl<N>(val, 10);
}
InplaceString<15> to_string(int val)
{
return to_string_impl<15>(val);
}
InplaceString<15> to_string(unsigned val)
{
return to_string_impl<15>(val);
}
InplaceString<23> to_string(long int val)
{
return to_string_impl<23>(val);
}
InplaceString<23> to_string(long long int val)
{
return to_string_impl<23>(val);
}
InplaceString<23> to_string(unsigned long val)
{
return to_string_impl<23>(val);
}
InplaceString<23> to_string(Hex val)
{
return to_string_impl<23>(val.val, 16);
}
InplaceString<23> to_string(Grouped val)
{
auto ungrouped = to_string_impl<23>(val.val);
InplaceString<23> res;
for (int pos = 0, len = ungrouped.m_length; pos != len; ++pos)
{
if (res.m_length and ((len - pos) % 3) == 0)
res.m_data[res.m_length++] = ',';
res.m_data[res.m_length++] = ungrouped.m_data[pos];
}
return res;
}
InplaceString<23> to_string(float val)
{
#if defined(__cpp_lib_to_chars)
return to_string_impl<23>(val, std::chars_format::general);
#else
InplaceString<23> res;
res.m_length = snprintf(res.m_data, 23, "%f", val);
return res;
#endif
}
InplaceString<7> to_string(Codepoint c)
{
InplaceString<7> res;
char* ptr = res.m_data;
utf8::dump(ptr, c);
res.m_length = (int)(ptr - res.m_data);
return res;
}
bool subsequence_match(StringView str, StringView subseq)
{
auto it = str.begin();
@ -327,92 +245,6 @@ WrapView::Iterator& WrapView::Iterator::operator++()
return *this;
}
template<typename AppendFunc>
void format_impl(StringView fmt, ArrayView<const StringView> params, AppendFunc append)
{
int implicitIndex = 0;
for (auto it = fmt.begin(), end = fmt.end(); it != end;)
{
auto opening = std::find(it, end, '{');
if (opening == end)
{
append(StringView{it, opening});
break;
}
else if (opening != it and *(opening-1) == '\\')
{
append(StringView{it, opening-1});
append('{');
it = opening + 1;
}
else
{
append(StringView{it, opening});
auto closing = std::find(opening, end, '}');
if (closing == end)
throw runtime_error("format string error, unclosed '{'");
auto format = std::find(opening+1, closing, ':');
const int index = opening+1 == format ? implicitIndex : str_to_int({opening+1, format});
if (index >= params.size())
throw runtime_error("format string parameter index too big");
if (format != closing)
{
char padding = ' ';
if (*(++format) == '0')
{
padding = '0';
++format;
}
for (ColumnCount width = str_to_int({format, closing}), len = params[index].column_length();
width > len; --width)
append(padding);
}
append(params[index]);
implicitIndex = index+1;
it = closing+1;
}
}
}
StringView format_to(ArrayView<char> buffer, StringView fmt, ArrayView<const StringView> params)
{
char* ptr = buffer.begin();
const char* end = buffer.end();
format_impl(fmt, params, [&](StringView s) mutable {
for (auto c : s)
{
if (ptr == end)
throw runtime_error("buffer is too small");
*ptr++ = c;
}
});
if (ptr == end)
throw runtime_error("buffer is too small");
*ptr = 0;
return { buffer.begin(), ptr };
}
void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params)
{
format_impl(fmt, params, append);
}
String format(StringView fmt, ArrayView<const StringView> params)
{
ByteCount size = fmt.length();
for (auto& s : params) size += s.length();
String res;
res.reserve(size);
format_impl(fmt, params, [&](StringView s) { res += s; });
return res;
}
String double_up(StringView s, StringView characters)
{
String res;

View File

@ -4,9 +4,10 @@
#include "string.hh"
#include "enum.hh"
#include "vector.hh"
#include "ranges.hh"
#include "optional.hh"
#include "utils.hh"
#include "format.hh"
#include "ranges.hh"
namespace Kakoune
{
@ -107,75 +108,6 @@ inline auto wrap_at(ColumnCount max_width)
int str_to_int(StringView str); // throws on error
Optional<int> str_to_int_ifp(StringView str);
template<size_t N>
struct InplaceString
{
static_assert(N < 256, "InplaceString cannot handle sizes >= 256");
constexpr operator StringView() const { return {m_data, ByteCount{m_length}}; }
operator String() const { return {m_data, ByteCount{m_length}}; }
unsigned char m_length{};
char m_data[N];
};
struct Hex { size_t val; };
constexpr Hex hex(size_t val) { return {val}; }
struct Grouped { size_t val; };
constexpr Grouped grouped(size_t val) { return {val}; }
InplaceString<15> to_string(int val);
InplaceString<15> to_string(unsigned val);
InplaceString<23> to_string(long int val);
InplaceString<23> to_string(unsigned long val);
InplaceString<23> to_string(long long int val);
InplaceString<23> to_string(Hex val);
InplaceString<23> to_string(Grouped val);
InplaceString<23> to_string(float val);
InplaceString<7> to_string(Codepoint c);
template<typename RealType, typename ValueType>
decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val)
{
return to_string((ValueType)val);
}
namespace detail
{
template<typename T> requires std::is_convertible_v<T, StringView>
StringView format_param(const T& val) { return val; }
template<typename T> requires (not std::is_convertible_v<T, StringView>)
decltype(auto) format_param(const T& val) { return to_string(val); }
}
String format(StringView fmt, ArrayView<const StringView> params);
template<typename... Types>
String format(StringView fmt, Types&&... params)
{
return format(fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
}
StringView format_to(ArrayView<char> buffer, StringView fmt, ArrayView<const StringView> params);
template<typename... Types>
StringView format_to(ArrayView<char> buffer, StringView fmt, Types&&... params)
{
return format_to(buffer, fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
}
void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params);
template<typename... Types>
void format_with(FunctionRef<void (StringView)> append, StringView fmt, Types&&... params)
{
return format_with(append, fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
}
String double_up(StringView s, StringView characters);
inline String quote(StringView s)

View File

@ -7,7 +7,7 @@
#include "file.hh"
#include "keys.hh"
#include "ranges.hh"
#include "string_utils.hh"
#include "format.hh"
#include "diff.hh"
#include <algorithm>

View File

@ -5,7 +5,6 @@
#include <cwchar>
#include "array_view.hh"
#include "ranges.hh"
#include "units.hh"
namespace Kakoune
@ -75,8 +74,12 @@ enum WordType { Word, WORD };
template<WordType word_type = Word>
inline bool is_word(Codepoint c, ConstArrayView<Codepoint> extra_word_chars = {'_'}) noexcept
{
return (c < 128 ? is_basic_alpha(c) or is_basic_digit(c) : iswalnum((wchar_t)c)) or
contains(extra_word_chars, c);
if (c < 128 ? is_basic_alpha(c) or is_basic_digit(c) : iswalnum((wchar_t)c))
return true;
for (auto cp : extra_word_chars)
if (c == cp)
return true;
return false;
}
template<>

View File

@ -1,13 +1,15 @@
#include "window.hh"
#include "assert.hh"
#include "buffer.hh"
#include "buffer_utils.hh"
#include "clock.hh"
#include "context.hh"
#include "highlighter.hh"
#include "hook_manager.hh"
#include "input_handler.hh"
#include "client.hh"
#include "buffer_utils.hh"
#include "debug.hh"
#include "option.hh"
#include "option_types.hh"
#include "profile.hh"

View File

@ -1,10 +1,8 @@
ui_out -ignore 7
ui_out -until '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
exec 5>fifo
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
printf '* noeol' >&5
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "*" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " noeol\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -ignore 2
ui_out -until '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "*" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " noeol\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
exec 5>&-
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "*fifo* 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[scratch]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "*fifo* 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[scratch]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'

View File

@ -2,11 +2,11 @@ ui_out -until '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
exec 5>fifo
echo '* line1' >&5
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "*" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " line1\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "*" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " line1\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
echo '* line2' >&5
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "*" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " line1\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "* line2\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "*" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " line1\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "* line2\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
dd if=/dev/zero bs=2049 count=1 2>/dev/null | sed s/././g >&5

View File

@ -1,6 +1,4 @@
ui_out -ignore 7
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ ":my-command " ] }'
ui_out -ignore 6
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
ui_out '{ "jsonrpc": "2.0", "method": "menu_show", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "aaa" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "bbb" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "ccc" }]], { "line": 0, "column": 0 }, { "fg": "white", "bg": "blue", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "white", "underline": "default", "attributes": [] }, "prompt"] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "menu_show", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "aaa" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "bbb" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "ccc" }]], { "line": 0, "column": 0 }, { "fg": "white", "bg": "blue", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "white", "underline": "default", "attributes": [] }, "prompt"] }'
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "<s-tab><ret>" ] }'

View File

@ -1,15 +1,4 @@
ui_out '{ "jsonrpc": "2.0", "method": "set_ui_options", "params": [{}] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "0" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "02\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "03\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "0" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "02\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "03\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
ui_in '{ "jsonrpc": "2.0", "method": "scroll", "params": [ 2 ] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "03\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "25\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "26\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
ui_out -until '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "03\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "25\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "26\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'