diff options
| author | Yukai Huang <yukaihuangtw@gmail.com> | 2025-06-27 23:11:23 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-27 23:11:23 +0800 |
| commit | 38a7a49ae85789f3b2aaaf7e263d6eabdccdf046 (patch) | |
| tree | 27a9ea5ed53be4c049c5177010cc889cdb4cbcb1 /src | |
| parent | 58414edb7b9b3d4cfde27a37ebec7f3906025675 (diff) | |
| parent | b3c3baef518d65f30a34b06764c6529b8247b837 (diff) | |
Merge branch 'master' into feature/native-cursor
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer_utils.cc | 3 | ||||
| -rw-r--r-- | src/client.cc | 3 | ||||
| -rw-r--r-- | src/client_manager.cc | 10 | ||||
| -rw-r--r-- | src/hash_map.hh | 7 | ||||
| -rw-r--r-- | src/highlighter.hh | 12 | ||||
| -rw-r--r-- | src/highlighters.cc | 225 | ||||
| -rw-r--r-- | src/normal.cc | 26 | ||||
| -rw-r--r-- | src/ranges.hh | 28 | ||||
| -rw-r--r-- | src/window.cc | 60 |
9 files changed, 130 insertions, 244 deletions
diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc index a2d2e709..bb64e9c1 100644 --- a/src/buffer_utils.cc +++ b/src/buffer_utils.cc @@ -290,7 +290,8 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, AutoScroll kak_assert(m_buffer.flags() & Buffer::Flags::Fifo); close_fd(); m_buffer.run_hook_in_own_context(Hook::BufCloseFifo, ""); - m_buffer.flags() &= ~(Buffer::Flags::Fifo | Buffer::Flags::NoUndo); + if (not m_buffer.values().contains(fifo_watcher_id)) + m_buffer.flags() &= ~(Buffer::Flags::Fifo | Buffer::Flags::NoUndo); } void read_fifo() diff --git a/src/client.cc b/src/client.cc index 2cb1c973..14b7b7bc 100644 --- a/src/client.cc +++ b/src/client.cc @@ -194,6 +194,9 @@ void Client::change_buffer(Buffer& buffer, Optional<FunctionRef<void()>> set_sel if (m_buffer_reload_dialog_opened) close_buffer_reload_dialog(); + if (context().buffer().flags() & Buffer::Flags::Locked) + throw runtime_error("Changing buffer is not allowed while current buffer is locked"); + buffer.flags() |= Buffer::Flags::Locked; OnScopeEnd unlock{[&] { buffer.flags() &= ~Buffer::Flags::Locked; }}; diff --git a/src/client_manager.cc b/src/client_manager.cc index 2e7d76e7..6798864e 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -67,17 +67,18 @@ Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui, int pi m_clients.emplace_back(client); auto& context = client->context(); - if (buffer->name() == "*scratch*") + if (context.buffer().name() == "*scratch*") context.print_status({"This *scratch* buffer won't be automatically saved", context.faces()["Information"]}); if (init_coord) { - auto& selections = context.selections_write_only(); - selections = SelectionList(*buffer, buffer->clamp(*init_coord)); + context.selections_write_only() = SelectionList(*buffer, context.buffer().clamp(*init_coord)); context.window().center_line(init_coord->line); } + auto(std::move(unlock)); // unlock now + try { context.hooks().run_hook(Hook::ClientCreate, context.name(), context); @@ -86,8 +87,7 @@ Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui, int pi catch (Kakoune::runtime_error& error) { context.print_status({error.what().str(), context.faces()["Error"]}); - context.hooks().run_hook(Hook::RuntimeError, error.what(), - context); + context.hooks().run_hook(Hook::RuntimeError, error.what(), context); } // Do not return the client if it already got moved to the trash diff --git a/src/hash_map.hh b/src/hash_map.hh index eef082dd..60ebc6ab 100644 --- a/src/hash_map.hh +++ b/src/hash_map.hh @@ -274,6 +274,7 @@ struct HashMap int index = find_index(key, hash); if (index >= 0) { + [[maybe_unused]] Item keepalive = std::move(m_items[index]); m_items.erase(m_items.begin() + index); m_index.remove(hash, index); m_index.ordered_fix_entries(index); @@ -287,7 +288,8 @@ struct HashMap int index = find_index(key, hash); if (index >= 0) { - constexpr_swap(m_items[index], m_items.back()); + [[maybe_unused]] Item keepalive = std::move(m_items[index]); + m_items[index] = std::move(m_items.back()); m_items.pop_back(); m_index.remove(hash, index); if (index != m_items.size()) @@ -296,7 +298,7 @@ struct HashMap } template<typename KeyType> requires IsHashCompatible<Key, KeyType> - constexpr void erase(const KeyType& key) { unordered_remove(key); } + constexpr void erase(const KeyType& key) { return unordered_remove(key); } template<typename KeyType> requires IsHashCompatible<Key, KeyType> constexpr void remove_all(const KeyType& key) @@ -305,6 +307,7 @@ struct HashMap for (int index = find_index(key, hash); index >= 0; index = find_index(key, hash)) { + [[maybe_unused]] Item keepalive = std::move(m_items[index]); m_items.erase(m_items.begin() + index); m_index.remove(hash, index); m_index.ordered_fix_entries(index); diff --git a/src/highlighter.hh b/src/highlighter.hh index 73520c53..fbeef9e4 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -22,11 +22,12 @@ using BufferRange = Range<BufferCoord>; enum class HighlightPass { - Wrap = 1 << 0, - Move = 1 << 1, - Colorize = 1 << 2, + Replace = 1 << 0, + Wrap = 1 << 1, + Move = 1 << 2, + Colorize = 1 << 3, - All = Wrap | Move | Colorize, + All = Replace | Wrap | Move | Colorize, }; constexpr bool with_bit_ops(Meta::Type<HighlightPass>) { return true; } @@ -43,11 +44,8 @@ struct DisplaySetup LineCount line_count; ColumnCount first_column; ColumnCount widget_columns; - // Position of the cursor in the window - DisplayCoord cursor_pos; // Offset of line and columns that must remain visible around cursor DisplayCoord scroll_offset; - bool ensure_cursor_visible; }; using HighlighterIdList = ConstArrayView<StringView>; diff --git a/src/highlighters.cc b/src/highlighters.cc index 25f93245..5dc2b38a 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -601,7 +601,7 @@ struct WrapHighlighter : Highlighter static constexpr StringView ms_id = "wrap"; - struct SplitPos{ ByteCount byte; ColumnCount column; }; + struct SplitPos{ DisplayLine::iterator atom_it; ByteCount byte; ColumnCount column; }; void do_highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange) override { @@ -613,42 +613,27 @@ struct WrapHighlighter : Highlighter return; const Buffer& buffer = context.context.buffer(); - const auto& cursor = context.context.selections().main().cursor(); const int tabstop = context.context.options()["tabstop"].get<int>(); - const LineCount win_height = context.context.window().dimensions().line; const ColumnCount marker_len = zero_if_greater(m_marker.column_length(), wrap_column); const Face face_marker = context.context.faces()["WrapMarker"]; for (auto it = display_buffer.lines().begin(); it != display_buffer.lines().end(); ++it) { - const LineCount buf_line = it->range().begin.line; - const ByteCount line_length = buffer[buf_line].length(); const ColumnCount indent = m_preserve_indent ? - zero_if_greater(line_indent(buffer, tabstop, buf_line), wrap_column) : 0_col; + zero_if_greater(line_indent(buffer, tabstop, it->range().begin.line), wrap_column) : 0_col; const ColumnCount prefix_len = std::max(marker_len, indent); - auto pos = next_split_pos(buffer, wrap_column, prefix_len, tabstop, buf_line, {0, 0}); - if (pos.byte == line_length) - continue; - - for (auto atom_it = it->begin(); - pos.byte != line_length and atom_it != it->end(); ) + SplitPos pos{it->begin(), 0, 0}; ; + while (next_split_pos(pos, it->end(), wrap_column, prefix_len)) { - const BufferCoord coord{buf_line, pos.byte}; - if (!atom_it->has_buffer_range() or - coord < atom_it->begin() or coord >= atom_it->end()) - { - ++atom_it; - continue; - } - auto& line = *it; - if (coord > atom_it->begin()) - atom_it = ++line.split(atom_it, coord); + if (pos.byte > 0 and pos.atom_it->type() == DisplayAtom::Range) + pos.atom_it = ++line.split(pos.atom_it, pos.atom_it->begin() + BufferCoord{0, pos.byte}); - DisplayLine new_line{ AtomList{ atom_it, line.end() } }; - line.erase(atom_it, line.end()); + auto coord = pos.atom_it->begin(); + DisplayLine new_line{ AtomList{ pos.atom_it, line.end() } }; + line.erase(pos.atom_it, line.end()); if (marker_len != 0) new_line.insert(new_line.begin(), {m_marker, face_marker}); @@ -658,23 +643,13 @@ struct WrapHighlighter : Highlighter it->replace(String{' ', indent - marker_len}); } - if (it+1 - display_buffer.lines().begin() == win_height) + it = display_buffer.lines().insert(it+1, new_line); + pos = SplitPos{it->begin(), 0, 0}; + if (pos.atom_it->type() != DisplayAtom::Range) // avoid infinite loop trying to split too long non-buffer ranges { - if (cursor >= new_line.range().begin) // strip first lines if cursor is not visible - { - display_buffer.lines().erase(display_buffer.lines().begin(), display_buffer.lines().begin()+1); - --it; - } - else - { - display_buffer.lines().erase(it+1, display_buffer.lines().end()); - return; - } + pos.column += pos.atom_it->content().column_length(); + ++pos.atom_it; } - it = display_buffer.lines().insert(it+1, new_line); - - pos = next_split_pos(buffer, wrap_column - prefix_len, prefix_len, tabstop, buf_line, pos); - atom_it = it->begin(); } } } @@ -688,80 +663,9 @@ struct WrapHighlighter : Highlighter if (wrap_column <= 0) return; - const Buffer& buffer = context.context.buffer(); - const auto& cursor = context.context.selections().main().cursor(); - const int tabstop = context.context.options()["tabstop"].get<int>(); - - auto line_wrap_count = [&](LineCount line, ColumnCount prefix_len) { - LineCount count = 0; - const ByteCount line_length = buffer[line].length(); - SplitPos pos{0, 0}; - while (true) - { - pos = next_split_pos(buffer, wrap_column - (pos.byte == 0 ? 0_col : prefix_len), - prefix_len, tabstop, line, pos); - if (pos.byte == line_length) - break; - ++count; - } - return count; - }; - - const auto win_height = context.context.window().dimensions().line; - // Disable horizontal scrolling when using a WrapHighlighter setup.first_column = 0; - setup.line_count = 0; setup.scroll_offset.column = 0; - - const ColumnCount marker_len = zero_if_greater(m_marker.column_length(), wrap_column); - - for (auto buf_line = setup.first_line, win_line = 0_line; - win_line < win_height or (setup.ensure_cursor_visible and buf_line <= cursor.line); - ++buf_line, ++setup.line_count) - { - if (buf_line >= buffer.line_count()) - break; - - const ColumnCount indent = m_preserve_indent ? - zero_if_greater(line_indent(buffer, tabstop, buf_line), wrap_column) : 0_col; - const ColumnCount prefix_len = std::max(marker_len, indent); - - if (buf_line == cursor.line) - { - SplitPos pos{0, 0}; - for (LineCount count = 0; true; ++count) - { - auto next_pos = next_split_pos(buffer, wrap_column - (pos.byte != 0 ? prefix_len : 0_col), - prefix_len, tabstop, buf_line, pos); - if (next_pos.byte > cursor.column) - { - setup.cursor_pos = DisplayCoord{ - win_line + count, - get_column(buffer, tabstop, cursor) - - pos.column + (pos.byte != 0 ? indent : 0_col) - }; - break; - } - pos = next_pos; - } - } - const auto wrap_count = line_wrap_count(buf_line, prefix_len); - win_line += wrap_count + 1; - - // scroll window to keep cursor visible, and update range as lines gets removed - while (setup.ensure_cursor_visible and - buf_line >= cursor.line and setup.first_line < cursor.line and - setup.cursor_pos.line + setup.scroll_offset.line >= win_height) - { - auto remove_count = 1 + line_wrap_count(setup.first_line, indent); - ++setup.first_line; - --setup.line_count; - setup.cursor_pos.line -= std::min(win_height, remove_count); - win_line -= remove_count; - kak_assert(setup.cursor_pos.line >= 0); - } - } } void fill_unique_ids(Vector<StringView>& unique_ids) const override @@ -769,79 +673,72 @@ struct WrapHighlighter : Highlighter unique_ids.push_back(ms_id); } - SplitPos next_split_pos(const Buffer& buffer, ColumnCount wrap_column, ColumnCount prefix_len, - int tabstop, LineCount line, SplitPos current) const + bool next_split_pos(SplitPos& pos, DisplayLine::iterator line_end, + ColumnCount wrap_column, ColumnCount prefix_len) const { - const ColumnCount target_column = current.column + wrap_column; - StringView content = buffer[line]; - - SplitPos pos = current; - SplitPos last_word_boundary = {0, 0}; - SplitPos last_WORD_boundary = {0, 0}; + SplitPos last_word_boundary = pos; + SplitPos last_WORD_boundary = pos; - auto update_boundaries = [&](Codepoint cp) { - if (not m_word_wrap) - return; - if (!is_word<Word>(cp)) + auto update_word_boundaries = [&](Codepoint cp) { + if (m_word_wrap and not is_word<Word>(cp)) last_word_boundary = pos; - if (!is_word<WORD>(cp)) + if (m_word_wrap and not is_word<WORD>(cp)) last_WORD_boundary = pos; }; - while (pos.byte < content.length() and pos.column < target_column) + while (pos.atom_it != line_end and pos.column < wrap_column) { - if (content[pos.byte] == '\t') + auto content = pos.atom_it->content(); + const char* it = &content[pos.byte]; + const Codepoint cp = utf8::read_codepoint(it, content.end()); + const ColumnCount width = codepoint_width(cp); + if (pos.column + width > wrap_column) // the target column was in the char { - const ColumnCount next_column = (pos.column / tabstop + 1) * tabstop; - if (next_column > target_column and pos.byte != current.byte) // the target column was in the tab - break; - pos.column = next_column; - ++pos.byte; - last_word_boundary = last_WORD_boundary = pos; + update_word_boundaries(cp); + break; } - else + pos.column += width; + pos.byte = (int)(it - content.begin()); + update_word_boundaries(cp); + if (it == content.end()) { - const char* it = &content[pos.byte]; - const Codepoint cp = utf8::read_codepoint(it, content.end()); - const ColumnCount width = codepoint_width(cp); - if (pos.column + width > target_column and pos.byte != current.byte) // the target column was in the char - { - update_boundaries(cp); - break; - } - pos.column += width; - pos.byte = (int)(it - content.begin()); - update_boundaries(cp); + ++pos.atom_it; + pos.byte = 0; } } + if (pos.atom_it == line_end) + return false; + auto content = pos.atom_it->content(); if (m_word_wrap and pos.byte < content.length()) { - auto find_split_pos = [&](SplitPos start_pos, auto is_word) -> Optional<SplitPos> { + auto find_split_pos = [&](SplitPos start_pos, auto is_word) { if (start_pos.byte == 0) - return {}; + return false; const char* it = &content[pos.byte]; // split at current position if is a word boundary if (not is_word(utf8::codepoint(it, content.end()), {'_'})) - return pos; + return true; // split at last word boundary if the word is shorter than our wrapping width ColumnCount word_length = pos.column - start_pos.column; while (it != content.end() and word_length <= (wrap_column - prefix_len)) { const Codepoint cp = utf8::read_codepoint(it, content.end()); if (not is_word(cp, {'_'})) - return start_pos; + { + pos = start_pos; + return true; + } word_length += codepoint_width(cp); } - return {}; + return false; }; - if (auto split = find_split_pos(last_WORD_boundary, is_word<WORD>)) - return *split; - if (auto split = find_split_pos(last_word_boundary, is_word<Word>)) - return *split; + if (find_split_pos(last_WORD_boundary, is_word<WORD>) or + find_split_pos(last_word_boundary, is_word<Word>)) + return true; } - return pos; + return true; } static ColumnCount line_indent(const Buffer& buffer, int tabstop, LineCount line) @@ -876,7 +773,7 @@ constexpr StringView WrapHighlighter::ms_id; struct TabulationHighlighter : Highlighter { - TabulationHighlighter() : Highlighter{HighlightPass::Move} {} + TabulationHighlighter() : Highlighter{HighlightPass::Replace} {} void do_highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange) override { @@ -947,7 +844,6 @@ struct TabulationHighlighter : Highlighter const ColumnCount offset = std::max(column + width - win_end, 0_col); setup.first_column += offset; - setup.cursor_pos.column -= offset; } }; @@ -968,7 +864,7 @@ const HighlighterDesc show_whitespace_desc = { struct ShowWhitespacesHighlighter : Highlighter { ShowWhitespacesHighlighter(String tab, String tabpad, String spc, String lf, String nbsp, String indent, bool only_trailing) - : Highlighter{HighlightPass::Move}, m_tab{std::move(tab)}, m_tabpad{std::move(tabpad)}, + : Highlighter{HighlightPass::Replace}, m_tab{std::move(tab)}, m_tabpad{std::move(tabpad)}, m_spc{std::move(spc)}, m_lf{std::move(lf)}, m_nbsp{std::move(nbsp)}, m_indent{std::move(indent)}, m_only_trailing{std::move(only_trailing)} {} @@ -1641,7 +1537,7 @@ const HighlighterDesc replace_ranges_desc = { "each spec is interpreted as a display line to display in place of the range", {} }; -struct ReplaceRangesHighlighter : OptionBasedHighlighter<RangeAndStringList, ReplaceRangesHighlighter, HighlightPass::Move> +struct ReplaceRangesHighlighter : OptionBasedHighlighter<RangeAndStringList, ReplaceRangesHighlighter, HighlightPass::Replace> { using ReplaceRangesHighlighter::OptionBasedHighlighter::OptionBasedHighlighter; private: @@ -1694,7 +1590,6 @@ private: auto& buffer = context.context.buffer(); auto& sels = context.context.selections(); auto& range_and_faces = get_option(context); - const int tabstop = context.context.options()["tabstop"].get<int>(); update_ranges(buffer, range_and_faces.prefix, range_and_faces.list); range_and_faces.prefix = buffer.timestamp(); @@ -1707,19 +1602,7 @@ private: if (range.first.line < setup.first_line and last.line >= setup.first_line) setup.first_line = range.first.line; - const auto& cursor = context.context.selections().main().cursor(); - if (cursor.line == last.line and cursor.column >= last.column) - { - auto first_column = get_column(buffer, tabstop, range.first); - auto last_column = get_column(buffer, tabstop, last); - auto replacement = parse_display_line(spec, context.context.faces()); - auto cursor_move = replacement.length() - ((range.first.line == last.line) ? last_column - first_column : last_column); - setup.cursor_pos.line -= last.line - range.first.line; - setup.cursor_pos.column += cursor_move; - } - - if (setup.ensure_cursor_visible and - last.line >= setup.first_line and + if (last.line >= setup.first_line and range.first.line <= setup.first_line + setup.line_count and range.first.line != last.line) { diff --git a/src/normal.cc b/src/normal.cc index 0d216436..cdc618a0 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -6,6 +6,7 @@ #include "changes.hh" #include "command_manager.hh" #include "context.hh" +#include "coord.hh" #include "diff.hh" #include "enum.hh" #include "face_registry.hh" @@ -537,8 +538,9 @@ void command(Context& context, NormalParams params) command(context, std::move(env_vars), params.reg); } -BufferCoord apply_diff(Buffer& buffer, BufferCoord pos, ArrayView<StringView> lines_before, StringView after) +BufferRange apply_diff(Buffer& buffer, BufferCoord pos, ArrayView<StringView> lines_before, StringView after) { + BufferCoord first = pos; const auto lines_after = after | split_after<StringView>('\n') | gather<Vector<StringView>>(); auto byte_count = [](auto&& lines, int first, int count) { @@ -546,6 +548,7 @@ BufferCoord apply_diff(Buffer& buffer, BufferCoord pos, ArrayView<StringView> li [](ByteCount l, StringView s) { return l + s.length(); }); }; + bool tried_to_erase_final_newline = false; for_each_diff(lines_before.begin(), (int)lines_before.size(), lines_after.begin(), (int)lines_after.size(), [&, posA = 0, posB = 0](DiffOp op, int len) mutable { @@ -557,17 +560,28 @@ BufferCoord apply_diff(Buffer& buffer, BufferCoord pos, ArrayView<StringView> li posB += len; break; case DiffOp::Add: + if (buffer.is_end(pos) and tried_to_erase_final_newline) + pos = buffer.prev(pos); pos = buffer.insert(pos, {lines_after[posB].begin(), lines_after[posB + len - 1].end()}).end; posB += len; break; case DiffOp::Remove: - pos = buffer.erase(pos, buffer.advance(pos, byte_count(lines_before, posA, len))); + { + BufferCoord end = buffer.advance(pos, byte_count(lines_before, posA, len)); + tried_to_erase_final_newline |= buffer.is_end(end); + pos = buffer.erase(pos, end); posA += len; break; } + } }); - return pos; + if (tried_to_erase_final_newline) + { + first = std::min(first, buffer.back_coord()); + pos = buffer.erase(buffer.back_coord(), buffer.end_coord()); + } + return {first, pos}; } template<bool replace> @@ -628,12 +642,12 @@ void pipe(Context& context, NormalParams params) if (in_lines.back().back() != '\n' and not out.empty() and out.back() == '\n') out.resize(out.length()-1, 0); - auto new_end = apply_diff(buffer, first, in_lines, out); - if (new_end != first) + auto [new_first, new_end] = apply_diff(buffer, first, in_lines, out); + if (new_first != new_end) { auto& min = sel.min(); auto& max = sel.max(); - min = first; + min = new_first; max = buffer.char_prev(new_end); } else diff --git a/src/ranges.hh b/src/ranges.hh index af13d6f8..affafda9 100644 --- a/src/ranges.hh +++ b/src/ranges.hh @@ -546,10 +546,10 @@ auto find(Range&& range, const T& value) } template<typename Range, typename T> -auto find_if(Range&& range, T op) +auto find_if(Range&& range, T&& op) { using std::begin; using std::end; - return std::find_if(begin(range), end(range), op); + return std::find_if(begin(range), end(range), std::forward<T>(op)); } template<typename Range, typename T> @@ -560,24 +560,24 @@ bool contains(Range&& range, const T& value) } template<typename Range, typename T> -bool all_of(Range&& range, T op) +bool all_of(Range&& range, T&& op) { using std::begin; using std::end; - return std::all_of(begin(range), end(range), op); + return std::all_of(begin(range), end(range), std::forward<T>(op)); } template<typename Range, typename T> -bool any_of(Range&& range, T op) +bool any_of(Range&& range, T&& op) { using std::begin; using std::end; - return std::any_of(begin(range), end(range), op); + return std::any_of(begin(range), end(range), std::forward<T>(op)); } template<typename Range, typename T> -auto remove_if(Range&& range, T op) +auto remove_if(Range&& range, T&& op) { using std::begin; using std::end; - return std::remove_if(begin(range), end(range), op); + return std::remove_if(begin(range), end(range), std::forward<T>(op)); } template<typename Range, typename U> @@ -596,7 +596,7 @@ template<typename Range, typename Init, typename BinOp> Init accumulate(Range&& c, Init&& init, BinOp&& op) { using std::begin; using std::end; - return std::accumulate(begin(c), end(c), init, op); + return std::accumulate(begin(c), end(c), init, std::forward<BinOp>(op)); } template<typename Range, typename Compare, typename Func> @@ -652,16 +652,12 @@ auto elements() }}; } -template<typename ExceptionType, bool exact_size, size_t... Indexes> -auto static_gather_impl(std::index_sequence<Indexes...>) -{ - return elements<ExceptionType, exact_size, Indexes...>(); -} - template<typename ExceptionType, size_t size, bool exact_size = true> auto static_gather() { - return static_gather_impl<ExceptionType, exact_size>(std::make_index_sequence<size>()); + return []<size_t... Indexes>(std::index_sequence<Indexes...>) { + return elements<ExceptionType, exact_size, Indexes...>(); + }(std::make_index_sequence<size>()); } } diff --git a/src/window.cc b/src/window.cc index 520d77e1..c65bebe8 100644 --- a/src/window.cc +++ b/src/window.cc @@ -132,7 +132,7 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context) return m_display_buffer; kak_assert(&buffer() == &context.buffer()); - const DisplaySetup setup = compute_display_setup(context); + DisplaySetup setup = compute_display_setup(context); for (LineCount line = 0; line < setup.line_count; ++line) { @@ -144,8 +144,26 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context) m_display_buffer.compute_range(); const BufferRange range{{0,0}, buffer().end_coord()}; - m_builtin_highlighters.highlight({context, setup, HighlightPass::Wrap, {}}, m_display_buffer, range); - m_builtin_highlighters.highlight({context, setup, HighlightPass::Move, {}}, m_display_buffer, range); + for (auto pass : {HighlightPass::Replace, HighlightPass::Wrap, HighlightPass::Move}) + m_builtin_highlighters.highlight({context, setup, pass, {}}, m_display_buffer, range); + + if (context.ensure_cursor_visible) + { + auto cursor_pos = display_coord(context.selections().main().cursor()); + kak_assert(cursor_pos); + + if (auto line_overflow = cursor_pos->line - m_dimensions.line + setup.scroll_offset.line + 1; line_overflow > 0) + { + lines.erase(lines.begin(), lines.begin() + (size_t)line_overflow); + setup.first_line = lines.begin()->range().begin.line; + } + + auto max_first_column = cursor_pos->column - (setup.widget_columns + setup.scroll_offset.column); + setup.first_column = std::min(setup.first_column, max_first_column); + + auto min_first_column = cursor_pos->column - (m_dimensions.column - setup.scroll_offset.column) + 1; + setup.first_column = std::max(setup.first_column, min_first_column); + } for (auto& line : m_display_buffer.lines()) line.trim_from(setup.widget_columns, setup.first_column, m_dimensions.column); @@ -203,11 +221,9 @@ DisplaySetup Window::compute_display_setup(const Context& context) const offset.line = std::min(offset.line, (m_dimensions.line + 1) / 2); offset.column = std::min(offset.column, (m_dimensions.column + 1) / 2); - const int tabstop = context.options()["tabstop"].get<int>(); const auto& cursor = context.selections().main().cursor(); - bool ensure_cursor_visible = context.ensure_cursor_visible; - if (ensure_cursor_visible) + if (context.ensure_cursor_visible) { if (cursor.line - offset.line < win_pos.line) win_pos.line = std::max(0_line, cursor.line - offset.line); @@ -216,39 +232,11 @@ DisplaySetup Window::compute_display_setup(const Context& context) const } win_pos.line = std::min(win_pos.line, buffer().line_count()-1); - DisplaySetup setup{ - win_pos.line, - m_dimensions.line, - win_pos.column, - 0_col, - {cursor.line - win_pos.line, - get_column(buffer(), tabstop, cursor) - win_pos.column}, - offset, - ensure_cursor_visible - }; - for (auto pass : { HighlightPass::Move, HighlightPass::Wrap }) + DisplaySetup setup{win_pos.line, m_dimensions.line, win_pos.column, 0_col, offset}; + for (auto pass : {HighlightPass::Move, HighlightPass::Wrap, HighlightPass::Replace}) m_builtin_highlighters.compute_display_setup({context, setup, pass, {}}, setup); check_display_setup(setup, *this); - // now ensure the cursor column is visible - if (ensure_cursor_visible) - { - auto underflow = std::max(-setup.first_column, - setup.cursor_pos.column - setup.scroll_offset.column); - if (underflow < 0) - { - setup.first_column += underflow; - setup.cursor_pos.column -= underflow; - } - auto overflow = setup.cursor_pos.column + setup.scroll_offset.column - (m_dimensions.column - setup.widget_columns) + 1; - if (overflow > 0) - { - setup.first_column += overflow; - setup.cursor_pos.column -= overflow; - } - check_display_setup(setup, *this); - } - return setup; } |
