summaryrefslogtreecommitdiff
path: root/src/selection.cc
AgeCommit message (Collapse)Author
2025-05-11Use linewise paste only if register is missing no trailing newlineJohannes Altmanninger
We use linewise paste if any of the pasted register elements has a trailing newline. As shown in the previous patch, this leads to awkward situations where insertion positions from <a-P> are not monotonically increasing. This complicated behavior is questionable. The root cause is that linewise paste may insert some strings that don't have a trailing newline. This leads to weird cases of GIGO, especially when using <a-P> when the last element is missing a trailing newline. Simplify the implementation by not activating linewise paste in that case. Instead of special-casing the last element, try to simplify the behavior further by using line-wise paste only if *all* elements are properly terminated. I can't think of a real-world case where the existing behavior would be desired. A regression test shows a change in behavior. Might be less weird now. The added test case is a copy except it uses "P" instead of "p" (the extra newline is because "d" deletes the last newline in the buffer which gets added back implicitly). (I think the list of register elements is never empty, so this should never cause a trivial linewise paste. Even if so, that would be fine because inserting nothing is a nop either way.) Fixes #5312
2025-05-11Work around non-forward insertions by linewise <a-P>Johannes Altmanninger
Given a buffer with two selections %(a)b%(c) Consider <a-P>, which inserts all elements of the dquote register, joined to a scalar string. This insertion happens once before each selection. Let the dquote register contain "\n" and "\nd". Since the first element ends in a newline, we enable linewise paste mode. The insertion at the first selection results in: contents: \n\nd%(a)b%(c) timestamps: 11111000000000 On top of that, the insertion at the second selection would result in: contents: \n\n\n\ndd%(a)b%(c) timestamps: 1111222221000000000 Observe that the second insertion actually takes place inside the text added by the first insertion. This is because we are inserting before the current line, and the first insertion does not end in a newline. This breaks the forward change tracker's assumption that each change takes place after the previous one, causing an assertion failure. We use this data structure to translate from old to new coordinates. Specifically, after the first insertion, the selection around %(c) which is initially 1.3,1.3 needs to be updated to 3.4,3.4. Work around this by instantiating a new ForwardChangesTracker after each step. This is very ugly because it's quadratic, and because it doesn't change the fact that the second insertion is made inside the first one. I think we can revert the workaround added by this patch, see the next patch. Closes #5312
2024-08-16include headers cleanupAdriĆ  Arrufat
2024-08-12Reduce headers dependency graphMaxime Coste
Move more code into the implementation files to reduce the amount of code pulled by headers.
2022-11-28Fix pasting after when selections are overlappingMaxime Coste
With overlapping selections, pasting after breaks assumption of SelectionList::for_each as our changes are no longer happening in increasing locations. We hence cannot rely on the ForwardChangeTracker in that case and have to rely on the more general (and more costly) ranges update logic. This interacts poorly with paste linewise pastes and we try to preserve the current behaviour by tracking the last paste position. Overall, this change really begs for overlapping selections to be removed, but we will fix them like that for now. Fixes #4779
2022-03-06src: Select the data inserted by `!` and `<a-!>`Frank LENORMAND
Closes #1468
2021-10-10Split InsertMode into InsertMode and PasteModeMaxime Coste
They are quite different use cases, and this allow moving InsertMode to input_handler.hh which is what uses it. This also cleans up the code as we can get rid of get_insert_pos and rely more on SelectionList::for_each.
2021-09-30rework selection insert/replace using a for_each methodMaxime Coste
expose that method so that various commands can take advantage of it for performance or simplicity purposes.
2021-08-30Take a function SelectionList::insert to get string to insertMaxime Coste
This makes it unnecessary to allocate Vector<String> to insert and allows to remove the insert_pos pointer hack by passing it to the callback.
2021-02-15Add + key to duplicate selections and <a-+> to merge overlapping onesMaxime Coste
This is an experiment and might get reverted if overlapping selections prove too cumbersome. Fixes #4041
2020-05-29Avoid to_remove vector in select helper functionMaxime Coste
Remove the need to allocate anything when removing selections.
2019-12-31Fix replacing at begining of bufferMaxime Coste
Fixes #3275
2019-12-18Cleanup replaced range selection logicMaxime Coste
Do not access Buffer::m_changes to find the inserted range, return it directly from Buffer::insert and Buffer::replace. This fixes a wrong behaviour where replacing at eof would lose the selected end of line (as the implementation does not actually replace that end of line)
2019-11-12Fix display column computationsJason Felice
Closes #3201
2019-11-12Add support for selecting and exporting selections in display columnsMaxime Coste
Fixes #2724
2019-11-12Add support for a -codepoint switch to the select commandMaxime Coste
2019-11-12Implement %val{selections_char_desc}Jason Felice
Fixes #3194
2019-11-09Avoid copy constructing BufferCoord when comparingJason Felice
2019-11-09Add static or const where usefulJason Felice
2019-11-07Merge selection list parsing into selection_list_from_stringsJason Felice
2019-05-29Do not merge selections on backspace in insert modeMaxime Coste
Fixes #2861
2019-04-01Add -timestamp switch support to the select commandMaxime Coste
Fixes #2829
2019-02-27Fixed all reorder warningsJustin Frank
2019-02-11Fix bug in 'itersel' handling that could result in unsorted selectionsMaxime Coste
2019-01-23Always select inserted text after pipingMaxime Coste
Relying on general selection update code is error prone due to diffing. Fixes #2394
2018-07-05Change `a` on end of line behaviour to be consistentMaxime Coste
`a` will just jump on next line, `a` on last end of line opens a new line beneath it. Fixes #1164
2018-07-05Tolerate restoring invalid coordinates from registerMaxime Coste
Clamp those selection after updating them to the current timestamp Fixes #2078
2018-07-05Store each selection as a separate element in a registerMaxime Coste
It makes more sense to use the list nature of the register to store the selections instead of storing them as a single string separated by spaces.
2018-07-05Make selection lists use the option list syntaxMaxime Coste
2018-03-09Detect no-op replaces and do not act on themMaxime Coste
This avoids recording no-op undo groups.
2018-03-04Remove SelectionList::update_timestamp()Maxime Coste
This single line member function was only used once, inline it directly.
2018-02-25Remove avoidance of end of linesMaxime Coste
Various places in Kakoune code used to modify selections so that cursors would not lie on an end of line. Remove those to increase Kakoune's consistency and simplicity. Now that end of lines are highlighted separately, they should not be handled specially in most commands.
2018-01-12Save/restore main selection from/to stringsMaxime Coste
Always consider that the first selection in the list is the main one, save selections that way. This approach was suggested by PR #1786 but the implementation here is different, and is used more generally whenever we save selections to strings. This is also the prefered way to work only on the main selection: save selections with Z, reduce to main with <space>, restore with z. Closes #1786 Fixes #1750
2017-12-12Detect invalid coordinates in selection_from_stringMaxime Coste
Fixes #1751
2017-11-27Fix compute_modified_ranges corner case that would crash on undoMaxime Coste
Fixes #1506 Fixes #1215
2017-11-01Add another assert to try to catch #1506Maxime Coste
2017-08-18Remove now trivial Selection::merge_with methodMaxime Coste
2017-08-18Change selection extension code to be simplerMaxime Coste
Selection extension now just keeps the anchor in place insead of trying to be smart depending on the direction of selections.
2017-07-19Add an assert to try to get more info on #1506Maxime Coste
2017-07-14Fix replacing reducing selections to their cursorMaxime Coste
Broken by 8650c99f131aae8b10eb2141f7c2152fff25b7d1
2017-07-14Fix assertion when replacing with empty stringsMaxime Coste
Replacing with empty strings is essentially a deletion, which means it can end up push some selections out of the buffer (imagine 3 a 2 empty line buffer, and deleting the second one). We are fixing the selections in SelectionList::erase, but we were not doing that in SelectionList::insert. Fixes #1504
2017-06-26Fix replacing last eol with a single eolMaxime Coste
2017-06-11Fix corner case in compute_modified_rangesMaxime Coste
2017-06-11Fix the Buffer::end() madnessMaxime Coste
Until now, buffer had multiple recognized end coordinates, either { line_count, 0 } or { line_count - 1, line[line_count - 1].length }. Now the only correct end coord is { line_count, 0 }, removing the need for various special cases.
2017-06-07Change merge_overlapping to guarantee we dont break the sortingMaxime Coste
In certain cases, we could end up with a unsorted selection list, leading to broken invariant.
2017-03-15Move SelectionList::set implementation out of the headerMaxime Coste
2017-03-03Ensure main selection index is correct directly in SelectionList::removeMaxime Coste
2017-01-13Update ranges highlighter options according to buffer changesMaxime Coste
2017-01-08Apply clang-tidy modernize to the codebaseMaxime Coste
2017-01-01Better handling of linewise inserting when we have multiple selections per lineMaxime Coste
Fixes #1053