CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Description
This is related to the recent addition of shortcuts to move lines up/down in text notes in #2089 (see #5418). When selecting multiple characters in one line, the selection is maintained correctly after moving the line. However, if the selection stretches over multiple lines, only the start of the selection is preserved correctly but it will end in the same line after the move. This can be annoying when we try to move multiple lines up/down as it only works correctly for the first move. I guess @eliandoran already noticed and mentioned this quirk.
The behavior is related to how ckeditor handles offsets. I once wrote a frontend script for those two shortcuts running into the same issue. At some point I ended up with a functional version that corrects the selection again after each move. It works perfectly for me since January 2024 now:
async function get_selected_blocks(editor) {
const blocks = editor.model.document.selection.getSelectedBlocks();
return Array.from(blocks);
}
async function text_move_lines_up() {
const editor = await api.getActiveContextTextEditor();
if (editor == null) return;
const selected_blocks = await get_selected_blocks(editor);
editor.model.change( writer => {
// Store selection offsets
const offsets = [
editor.model.document.selection.getFirstPosition().offset,
editor.model.document.selection.getLastPosition().offset
];
// Move items (blocks are items are nodes apperently)
for ( const block of selected_blocks ) {
// Get the previous position (null if none)
let target = block.previousSibling;
if (target != null) {
target = writer.createPositionBefore(target);
writer.insert(block, target);
} else {
console.log('Cannot move items further up, first position reached');
break;
}
}
// Restore selection to all items if many have been moved
const range = writer.createRange(
writer.createPositionAt(selected_blocks[0], offsets[0]),
writer.createPositionAt(
selected_blocks[selected_blocks.length - 1], offsets[1]));
writer.setSelection(range);
});
}
// Move lines down
async function text_move_lines_down() {
const editor = await api.getActiveContextTextEditor();
if (editor == null) return;
const selected_blocks = await get_selected_blocks(editor);
editor.model.change( writer => {
// Remember selection offsets to restore them later
const offsets = [
editor.model.document.selection.getFirstPosition().offset,
editor.model.document.selection.getLastPosition().offset
];
// Move items (blocks are items are nodes apperently)
for ( const block of selected_blocks.slice().reverse() ) {
// Get the next position (null if none)
const target = writer.createPositionAfter(block.nextSibling);
if (target != null) {
writer.insert(block, target);
} else {
console.log('Cannot move items further down, last position reached');
break;
}
}
// Restore selection to all items if many have been moved
const range = writer.createRange(
writer.createPositionAt(selected_blocks[0], offsets[0]),
writer.createPositionAt(
selected_blocks[selected_blocks.length - 1], offsets[1]));
writer.setSelection(range);
});
}
api.bindGlobalShortcut('ctrl+alt+up', text_move_lines_up);
api.bindGlobalShortcut('ctrl+alt+down', text_move_lines_down);
(Sorry for the snake cases.)
You can copy/paste this into a frontend code note, execute it (on frontend startup if you like) and test the behavior in a text note with ctrl+alt+up/down
.
One quirk remains: if the selection ends or starts at the line end or start, one line is sometimes unselected after moving. This should be very easy to fix but I was too lazy so far. Plus, it can always be avoided by letting the selection start or end one character later or earlier. In the worst case you end up with the default behavior as it is currently implemented in #2089.
I remember a lot of weirdness, inconsistencies, and frustration when I implemented this. If the approach seems a bit twisted and weird, believe me, I started with a more recommended and intuitive approach. Yet that's what I ended up with.
TriliumNext Version
0.94.0
What operating system are you using?
Other Linux
What is your setup?
Local + server sync
Operating System Version
Linux 6.12.31-1-lts
Error logs
Produces no errors