shahnevis-core
Version:
**Shahnevis Core** is a lightweight and flexible library for building custom code editors. It provides essential features like syntax highlighting, a minimap, multi-cursor support, line numbering, and plugin management. This library is framework-agnostic,
181 lines (155 loc) • 6.75 kB
JavaScript
/*
This file is part of Shahnevis Core.
Copyright (C) 2024 shahrooz saneidarani (github.com/shahroozD)
Shahnevis Core is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Shahnevis Core is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { updateSyntaxHighlighting } from '../core/highlighting.js';
import { computeTotalSpan, updateFoldedBlocksAfterSwap } from './folding.js';
// moveLine =====================
// Function to move line up
function moveLineUp(editor, foldingUtils) {
var _lines$lineIndex;
var foldedBlocks = foldingUtils.getFoldedBlocksById();
var cursorPosition = editor.selectionStart;
var lines = editor.value.split("\n");
// Get the line number of the cursor
var lineIndex = editor.value.substring(0, cursorPosition).split("\n").length - 1;
var actualLineIndex = editor.value.substring(0, cursorPosition).split("\n").length - 1;
var lastBlockNumber = 0;
var lastBlockSize = 0;
for (var key in foldedBlocks) {
var numKey = parseInt(key, 10);
if ((numKey > lastBlockNumber + lastBlockSize || lastBlockNumber == 0) && numKey < actualLineIndex) {
lastBlockNumber = numKey;
if (lastBlockNumber != 0) lastBlockSize = 0;
}
if (numKey < actualLineIndex) {
actualLineIndex += foldedBlocks[key].length;
lastBlockSize += foldedBlocks[key].length;
} else break;
}
// If it's the first line, do nothing
if (lineIndex === 0) return;
// Swap the current line with the previous line
var temp = lines[lineIndex];
lines[lineIndex] = lines[lineIndex - 1];
lines[lineIndex - 1] = temp;
console.log("???????????????????");
// Update the editor content
editor.value = lines.join("\n");
foldingUtils.updateFoldedBlocks(updateFoldedBlocksAfterSwap(foldedBlocks, actualLineIndex, foldedBlocks[actualLineIndex - lastBlockSize - 1] ? lastBlockNumber : actualLineIndex - 1));
// Restore the cursor position
var newCursorPos = cursorPosition - ((_lines$lineIndex = lines[lineIndex]) === null || _lines$lineIndex === void 0 ? void 0 : _lines$lineIndex.length) - 1; // Adjust cursor for the swapped line
editor.selectionStart = editor.selectionEnd = newCursorPos;
}
// Function to move line down
function moveLineDown(editor, foldingUtils) {
var _lines$lineIndex2;
var foldedBlocks = foldingUtils.getFoldedBlocksById();
var cursorPosition = editor.selectionStart;
var lines = editor.value.split("\n");
// Get the line number of the cursor
var lineIndex = editor.value.substring(0, cursorPosition).split("\n").length - 1;
var actualLineIndex = editor.value.substring(0, cursorPosition).split("\n").length - 1;
for (var key in foldedBlocks) {
var numKey = parseInt(key, 10);
if (numKey < actualLineIndex) actualLineIndex += foldedBlocks[key].length;else break;
}
// If it's the last line, do nothing
if (lineIndex === lines.length - 1) return;
// Swap the current line with the next line
var temp = lines[lineIndex];
lines[lineIndex] = lines[lineIndex + 1];
lines[lineIndex + 1] = temp;
// Update the editor content
editor.value = lines.join("\n");
foldingUtils.updateFoldedBlocks(updateFoldedBlocksAfterSwap(foldedBlocks, actualLineIndex, actualLineIndex + 1));
// Restore the cursor position
var newCursorPos = cursorPosition + ((_lines$lineIndex2 = lines[lineIndex]) === null || _lines$lineIndex2 === void 0 ? void 0 : _lines$lineIndex2.length) + 1; // Adjust cursor for the swapped line
editor.selectionStart = editor.selectionEnd = newCursorPos;
}
export function handleMoveLine(e, editor, foldingUtils) {
if (e.altKey) {
if (e.key === 'ArrowUp') {
e.preventDefault(); // Prevent default browser behavior (if any)
moveLineUp(editor, foldingUtils);
} else if (e.key === 'ArrowDown') {
e.preventDefault(); // Prevent default browser behavior (if any)
moveLineDown(editor, foldingUtils);
}
}
// Update syntax highlighting if needed
var highlight = null;
updateSyntaxHighlighting(editor, highlight);
}
// moveLine =====================
// multi-line ===================
var anchorLineStart = null;
var anchorLineEnd = null;
// Function to handle multi-line selection
function multiLineSelect(direction, editor) {
var cursorPosition = editor.selectionStart;
var lines = editor.value.split("\n");
// Get the current line number
var lineIndex = editor.value.substring(0, cursorPosition).split("\n").length - 1;
// Initialize anchor points if this is the first multi-line select
if (anchorLineStart === null || anchorLineEnd === null) {
anchorLineStart = lineIndex;
anchorLineEnd = lineIndex;
}
// Move selection up or down
if (direction === 'up' && anchorLineStart > 0) {
anchorLineStart--;
} else if (direction === 'down' && anchorLineEnd < lines.length - 1) {
anchorLineEnd++;
}
// Select from the anchor start line to the anchor end line
var start = getPositionForLine(anchorLineStart, editor);
var end = getPositionForLine(anchorLineEnd, editor) + lines[anchorLineEnd].length;
editor.setSelectionRange(start, end);
}
// Get the cursor position at the start of a given line
function getPositionForLine(lineIndex, editor) {
var lines = editor.value.split("\n");
var position = 0;
for (var i = 0; i < lineIndex; i++) {
position += lines[i].length + 1; // +1 for the newline character
}
return position;
}
// handle for Ctrl + Alt + Arrow keys
export function handleMultiSelect(e, editor) {
if (e.ctrlKey && e.altKey) {
if (e.key === 'ArrowUp') {
e.preventDefault(); // Prevent default browser behavior
multiLineSelect('up', editor);
} else if (e.key === 'ArrowDown') {
e.preventDefault(); // Prevent default browser behavior
multiLineSelect('down', editor);
}
}
// Update syntax highlighting if needed
var highlight = null;
updateSyntaxHighlighting(editor, highlight);
}
// Function to reset anchor points when the selection is cleared or changed manually
export function resetAnchorPoints(editor) {
editor.addEventListener('click', function () {
anchorLineStart = null;
anchorLineEnd = null;
});
editor.addEventListener('input', function () {
anchorLineStart = null;
anchorLineEnd = null;
});
}
// multi-line ===================