summaryrefslogtreecommitdiff
path: root/SI/.obsidian/plugins/obsidian-editor-shortcuts/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'SI/.obsidian/plugins/obsidian-editor-shortcuts/main.js')
-rw-r--r--SI/.obsidian/plugins/obsidian-editor-shortcuts/main.js1342
1 files changed, 1342 insertions, 0 deletions
diff --git a/SI/.obsidian/plugins/obsidian-editor-shortcuts/main.js b/SI/.obsidian/plugins/obsidian-editor-shortcuts/main.js
new file mode 100644
index 0000000..5ea296c
--- /dev/null
+++ b/SI/.obsidian/plugins/obsidian-editor-shortcuts/main.js
@@ -0,0 +1,1342 @@
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __defProps = Object.defineProperties;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getOwnPropSymbols = Object.getOwnPropertySymbols;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __propIsEnum = Object.prototype.propertyIsEnumerable;
+var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
+var __spreadValues = (a, b) => {
+ for (var prop in b || (b = {}))
+ if (__hasOwnProp.call(b, prop))
+ __defNormalProp(a, prop, b[prop]);
+ if (__getOwnPropSymbols)
+ for (var prop of __getOwnPropSymbols(b)) {
+ if (__propIsEnum.call(b, prop))
+ __defNormalProp(a, prop, b[prop]);
+ }
+ return a;
+};
+var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
+var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
+var __export = (target, all) => {
+ __markAsModule(target);
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __reExport = (target, module2, desc) => {
+ if (module2 && typeof module2 === "object" || typeof module2 === "function") {
+ for (let key of __getOwnPropNames(module2))
+ if (!__hasOwnProp.call(target, key) && key !== "default")
+ __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
+ }
+ return target;
+};
+var __toModule = (module2) => {
+ return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
+};
+var __async = (__this, __arguments, generator) => {
+ return new Promise((resolve, reject) => {
+ var fulfilled = (value) => {
+ try {
+ step(generator.next(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var rejected = (value) => {
+ try {
+ step(generator.throw(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
+ step((generator = generator.apply(__this, __arguments)).next());
+ });
+};
+
+// src/main.ts
+__export(exports, {
+ default: () => CodeEditorShortcuts
+});
+var import_obsidian3 = __toModule(require("obsidian"));
+
+// src/constants.ts
+var CASE;
+(function(CASE2) {
+ CASE2["UPPER"] = "upper";
+ CASE2["LOWER"] = "lower";
+ CASE2["TITLE"] = "title";
+ CASE2["NEXT"] = "next";
+})(CASE || (CASE = {}));
+var LOWERCASE_ARTICLES = ["the", "a", "an"];
+var SEARCH_DIRECTION;
+(function(SEARCH_DIRECTION2) {
+ SEARCH_DIRECTION2["FORWARD"] = "forward";
+ SEARCH_DIRECTION2["BACKWARD"] = "backward";
+})(SEARCH_DIRECTION || (SEARCH_DIRECTION = {}));
+var MATCHING_BRACKETS = {
+ "[": "]",
+ "(": ")",
+ "{": "}"
+};
+var MATCHING_QUOTES = {
+ "'": "'",
+ '"': '"',
+ "`": "`"
+};
+var MATCHING_QUOTES_BRACKETS = __spreadValues(__spreadValues({}, MATCHING_QUOTES), MATCHING_BRACKETS);
+var CODE_EDITOR;
+(function(CODE_EDITOR2) {
+ CODE_EDITOR2["SUBLIME"] = "sublime";
+ CODE_EDITOR2["VSCODE"] = "vscode";
+})(CODE_EDITOR || (CODE_EDITOR = {}));
+var MODIFIER_KEYS = [
+ "Control",
+ "Shift",
+ "Alt",
+ "Meta",
+ "CapsLock",
+ "Fn"
+];
+var LIST_CHARACTER_REGEX = /^\s*(-|\+|\*|\d+\.|>) (\[.\] )?/;
+
+// src/state.ts
+var SettingsState = {
+ autoInsertListPrefix: true
+};
+
+// src/utils.ts
+var defaultMultipleSelectionOptions = { repeatSameLineActions: true };
+var withMultipleSelectionsNew = (editor, callback, options = defaultMultipleSelectionOptions) => {
+ const selections = editor.listSelections();
+ let selectionIndexesToProcess;
+ const newSelections = [];
+ const changes = [];
+ if (!options.repeatSameLineActions) {
+ const seenLines = [];
+ selectionIndexesToProcess = selections.reduce((indexes, currSelection, currIndex) => {
+ const currentLine = currSelection.head.line;
+ if (!seenLines.includes(currentLine)) {
+ seenLines.push(currentLine);
+ indexes.push(currIndex);
+ }
+ return indexes;
+ }, []);
+ }
+ for (let i = 0; i < selections.length; i++) {
+ if (selectionIndexesToProcess && !selectionIndexesToProcess.includes(i)) {
+ continue;
+ }
+ const { changes: newChanges, newSelection } = callback(editor, selections[i], __spreadProps(__spreadValues({}, options.args), {
+ iteration: i
+ }));
+ changes.push(...newChanges);
+ if (options.combineSameLineSelections) {
+ const existingSameLineSelection = newSelections.find((selection) => selection.from.line === newSelection.from.line);
+ if (existingSameLineSelection) {
+ existingSameLineSelection.from.ch = 0;
+ continue;
+ }
+ }
+ newSelections.push(newSelection);
+ }
+ editor.transaction({
+ changes,
+ selections: newSelections
+ });
+};
+var withMultipleSelections = (editor, callback, options = defaultMultipleSelectionOptions) => {
+ const { cm } = editor;
+ const selections = editor.listSelections();
+ let selectionIndexesToProcess;
+ let newSelections = [];
+ if (!options.repeatSameLineActions) {
+ const seenLines = [];
+ selectionIndexesToProcess = selections.reduce((indexes, currSelection, currIndex) => {
+ const currentLine = currSelection.head.line;
+ if (!seenLines.includes(currentLine)) {
+ seenLines.push(currentLine);
+ indexes.push(currIndex);
+ }
+ return indexes;
+ }, []);
+ }
+ const applyCallbackOnSelections = () => {
+ for (let i = 0; i < selections.length; i++) {
+ if (selectionIndexesToProcess && !selectionIndexesToProcess.includes(i)) {
+ continue;
+ }
+ const selection = editor.listSelections()[i];
+ if (selection) {
+ const newSelection = callback(editor, selection, options.args);
+ newSelections.push(newSelection);
+ }
+ }
+ if (options.customSelectionHandler) {
+ newSelections = options.customSelectionHandler(newSelections);
+ }
+ editor.setSelections(newSelections);
+ };
+ if (cm && cm.operation) {
+ cm.operation(applyCallbackOnSelections);
+ } else {
+ console.debug("cm object not found, operations will not be buffered");
+ applyCallbackOnSelections();
+ }
+};
+var iterateCodeMirrorDivs = (callback) => {
+ let codeMirrors;
+ codeMirrors = document.querySelectorAll(".cm-content");
+ if (codeMirrors.length === 0) {
+ codeMirrors = document.querySelectorAll(".CodeMirror");
+ }
+ codeMirrors.forEach(callback);
+};
+var getLineStartPos = (line) => ({
+ line,
+ ch: 0
+});
+var getLineEndPos = (line, editor) => ({
+ line,
+ ch: editor.getLine(line).length
+});
+var getSelectionBoundaries = (selection) => {
+ let { anchor: from, head: to } = selection;
+ if (from.line > to.line) {
+ [from, to] = [to, from];
+ }
+ if (from.line === to.line && from.ch > to.ch) {
+ [from, to] = [to, from];
+ }
+ return { from, to, hasTrailingNewline: to.line > from.line && to.ch === 0 };
+};
+var getLeadingWhitespace = (lineContent) => {
+ const indentation = lineContent.match(/^\s+/);
+ return indentation ? indentation[0] : "";
+};
+var isLetterCharacter = (char) => /\p{L}\p{M}*/u.test(char);
+var isDigit = (char) => /\d/.test(char);
+var isLetterOrDigit = (char) => isLetterCharacter(char) || isDigit(char);
+var wordRangeAtPos = (pos, lineContent) => {
+ let start = pos.ch;
+ let end = pos.ch;
+ while (start > 0 && isLetterOrDigit(lineContent.charAt(start - 1))) {
+ start--;
+ }
+ while (end < lineContent.length && isLetterOrDigit(lineContent.charAt(end))) {
+ end++;
+ }
+ return {
+ anchor: {
+ line: pos.line,
+ ch: start
+ },
+ head: {
+ line: pos.line,
+ ch: end
+ }
+ };
+};
+var findPosOfNextCharacter = ({
+ editor,
+ startPos,
+ checkCharacter,
+ searchDirection
+}) => {
+ let { line, ch } = startPos;
+ let lineContent = editor.getLine(line);
+ let matchFound = false;
+ let matchedChar;
+ if (searchDirection === SEARCH_DIRECTION.BACKWARD) {
+ while (line >= 0) {
+ const char = lineContent.charAt(Math.max(ch - 1, 0));
+ matchFound = checkCharacter(char);
+ if (matchFound) {
+ matchedChar = char;
+ break;
+ }
+ ch--;
+ if (ch <= 0) {
+ line--;
+ if (line >= 0) {
+ lineContent = editor.getLine(line);
+ ch = lineContent.length;
+ }
+ }
+ }
+ } else {
+ while (line < editor.lineCount()) {
+ const char = lineContent.charAt(ch);
+ matchFound = checkCharacter(char);
+ if (matchFound) {
+ matchedChar = char;
+ break;
+ }
+ ch++;
+ if (ch >= lineContent.length) {
+ line++;
+ lineContent = editor.getLine(line);
+ ch = 0;
+ }
+ }
+ }
+ return matchFound ? {
+ match: matchedChar,
+ pos: {
+ line,
+ ch
+ }
+ } : null;
+};
+var hasSameSelectionContent = (editor, selections) => new Set(selections.map((selection) => {
+ const { from, to } = getSelectionBoundaries(selection);
+ return editor.getRange(from, to);
+})).size === 1;
+var getSearchText = ({
+ editor,
+ allSelections,
+ autoExpand
+}) => {
+ const singleSearchText = hasSameSelectionContent(editor, allSelections);
+ const firstSelection = allSelections[0];
+ const { from, to } = getSelectionBoundaries(firstSelection);
+ let searchText = editor.getRange(from, to);
+ if (searchText.length === 0 && autoExpand) {
+ const wordRange = wordRangeAtPos(from, editor.getLine(from.line));
+ searchText = editor.getRange(wordRange.anchor, wordRange.head);
+ }
+ return {
+ searchText,
+ singleSearchText
+ };
+};
+var escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+var withWordBoundaries = (input) => `(?<=\\W|^)${input}(?=\\W|$)`;
+var findAllMatches = ({
+ searchText,
+ searchWithinWords,
+ documentContent
+}) => {
+ const escapedSearchText = escapeRegex(searchText);
+ const searchExpression = new RegExp(searchWithinWords ? escapedSearchText : withWordBoundaries(escapedSearchText), "g");
+ return Array.from(documentContent.matchAll(searchExpression));
+};
+var findNextMatchPosition = ({
+ editor,
+ latestMatchPos,
+ searchText,
+ searchWithinWords,
+ documentContent
+}) => {
+ const latestMatchOffset = editor.posToOffset(latestMatchPos);
+ const matches = findAllMatches({
+ searchText,
+ searchWithinWords,
+ documentContent
+ });
+ let nextMatch = null;
+ for (const match of matches) {
+ if (match.index > latestMatchOffset) {
+ nextMatch = {
+ anchor: editor.offsetToPos(match.index),
+ head: editor.offsetToPos(match.index + searchText.length)
+ };
+ break;
+ }
+ }
+ if (!nextMatch) {
+ const selectionIndexes = editor.listSelections().map((selection) => {
+ const { from } = getSelectionBoundaries(selection);
+ return editor.posToOffset(from);
+ });
+ for (const match of matches) {
+ if (!selectionIndexes.includes(match.index)) {
+ nextMatch = {
+ anchor: editor.offsetToPos(match.index),
+ head: editor.offsetToPos(match.index + searchText.length)
+ };
+ break;
+ }
+ }
+ }
+ return nextMatch;
+};
+var findAllMatchPositions = ({
+ editor,
+ searchText,
+ searchWithinWords,
+ documentContent
+}) => {
+ const matches = findAllMatches({
+ searchText,
+ searchWithinWords,
+ documentContent
+ });
+ const matchPositions = [];
+ for (const match of matches) {
+ matchPositions.push({
+ anchor: editor.offsetToPos(match.index),
+ head: editor.offsetToPos(match.index + searchText.length)
+ });
+ }
+ return matchPositions;
+};
+var toTitleCase = (selectedText) => {
+ return selectedText.split(/(\s+)/).map((word, index, allWords) => {
+ if (index > 0 && index < allWords.length - 1 && LOWERCASE_ARTICLES.includes(word.toLowerCase())) {
+ return word.toLowerCase();
+ }
+ return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
+ }).join("");
+};
+var getNextCase = (selectedText) => {
+ const textUpper = selectedText.toUpperCase();
+ const textLower = selectedText.toLowerCase();
+ const textTitle = toTitleCase(selectedText);
+ switch (selectedText) {
+ case textUpper: {
+ return textLower;
+ }
+ case textLower: {
+ return textTitle;
+ }
+ case textTitle: {
+ return textUpper;
+ }
+ default: {
+ return textUpper;
+ }
+ }
+};
+var isNumeric = (input) => input.length > 0 && !isNaN(+input);
+var getNextListPrefix = (text, direction) => {
+ const listChars = text.match(LIST_CHARACTER_REGEX);
+ if (listChars && listChars.length > 0) {
+ let prefix = listChars[0].trimStart();
+ const isEmptyListItem = prefix === listChars.input.trimStart();
+ if (isEmptyListItem) {
+ return null;
+ }
+ if (isNumeric(prefix) && direction === "after") {
+ prefix = +prefix + 1 + ". ";
+ }
+ if (prefix.startsWith("- [") && !prefix.includes("[ ]")) {
+ prefix = "- [ ] ";
+ }
+ return prefix;
+ }
+ return "";
+};
+var formatRemainingListPrefixes = (editor, fromLine, indentation) => {
+ const changes = [];
+ for (let i = fromLine; i < editor.lineCount(); i++) {
+ const contentsOfCurrentLine = editor.getLine(i);
+ const listPrefixRegex = new RegExp(`^${indentation}\\d+\\.`);
+ const lineStartsWithNumberPrefix = listPrefixRegex.test(contentsOfCurrentLine);
+ if (!lineStartsWithNumberPrefix) {
+ break;
+ }
+ const replacementContent = contentsOfCurrentLine.replace(/\d+\./, (match) => +match + 1 + ".");
+ changes.push({
+ from: { line: i, ch: 0 },
+ to: { line: i, ch: contentsOfCurrentLine.length },
+ text: replacementContent
+ });
+ }
+ if (changes.length > 0) {
+ editor.transaction({ changes });
+ }
+};
+var toggleVaultConfig = (app, setting) => {
+ const value = app.vault.getConfig(setting);
+ setVaultConfig(app, setting, !value);
+};
+var setVaultConfig = (app, setting, value) => {
+ app.vault.setConfig(setting, value);
+};
+
+// src/actions.ts
+var insertLineAbove = (editor, selection, args) => {
+ const { line } = selection.head;
+ const startOfCurrentLine = getLineStartPos(line);
+ const contentsOfCurrentLine = editor.getLine(line);
+ const indentation = getLeadingWhitespace(contentsOfCurrentLine);
+ let listPrefix = "";
+ if (SettingsState.autoInsertListPrefix && line > 0 && editor.getLine(line - 1).trim().length > 0) {
+ listPrefix = getNextListPrefix(contentsOfCurrentLine, "before");
+ if (isNumeric(listPrefix)) {
+ formatRemainingListPrefixes(editor, line, indentation);
+ }
+ }
+ const changes = [
+ { from: startOfCurrentLine, text: indentation + listPrefix + "\n" }
+ ];
+ const newSelection = {
+ from: __spreadProps(__spreadValues({}, startOfCurrentLine), {
+ line: startOfCurrentLine.line + args.iteration,
+ ch: indentation.length + listPrefix.length
+ })
+ };
+ return {
+ changes,
+ newSelection
+ };
+};
+var insertLineBelow = (editor, selection, args) => {
+ const { line } = selection.head;
+ const startOfCurrentLine = getLineStartPos(line);
+ const endOfCurrentLine = getLineEndPos(line, editor);
+ const contentsOfCurrentLine = editor.getLine(line);
+ const indentation = getLeadingWhitespace(contentsOfCurrentLine);
+ let listPrefix = "";
+ if (SettingsState.autoInsertListPrefix) {
+ listPrefix = getNextListPrefix(contentsOfCurrentLine, "after");
+ if (listPrefix === null) {
+ const changes2 = [
+ { from: startOfCurrentLine, to: endOfCurrentLine, text: "" }
+ ];
+ const newSelection2 = {
+ from: {
+ line,
+ ch: 0
+ }
+ };
+ return {
+ changes: changes2,
+ newSelection: newSelection2
+ };
+ }
+ if (isNumeric(listPrefix)) {
+ formatRemainingListPrefixes(editor, line + 1, indentation);
+ }
+ }
+ const changes = [
+ { from: endOfCurrentLine, text: "\n" + indentation + listPrefix }
+ ];
+ const newSelection = {
+ from: {
+ line: line + 1 + args.iteration,
+ ch: indentation.length + listPrefix.length
+ }
+ };
+ return {
+ changes,
+ newSelection
+ };
+};
+var numLinesDeleted = 0;
+var deleteLine = (editor, selection, args) => {
+ const { from, to, hasTrailingNewline } = getSelectionBoundaries(selection);
+ if (to.line === editor.lastLine()) {
+ const previousLine = Math.max(0, from.line - 1);
+ const endOfPreviousLine = getLineEndPos(previousLine, editor);
+ const changes2 = [
+ {
+ from: from.line === 0 ? getLineStartPos(0) : endOfPreviousLine,
+ to: to.ch === 0 ? getLineStartPos(to.line) : getLineEndPos(to.line, editor),
+ text: ""
+ }
+ ];
+ const newSelection2 = {
+ from: {
+ line: previousLine,
+ ch: Math.min(from.ch, endOfPreviousLine.ch)
+ }
+ };
+ return {
+ changes: changes2,
+ newSelection: newSelection2
+ };
+ }
+ if (args.iteration === 0) {
+ numLinesDeleted = 0;
+ }
+ const toLine = hasTrailingNewline ? to.line - 1 : to.line;
+ const endOfNextLine = getLineEndPos(toLine + 1, editor);
+ const changes = [
+ {
+ from: getLineStartPos(from.line),
+ to: getLineStartPos(toLine + 1),
+ text: ""
+ }
+ ];
+ const newSelection = {
+ from: {
+ line: from.line - numLinesDeleted,
+ ch: Math.min(to.ch, endOfNextLine.ch)
+ }
+ };
+ numLinesDeleted += toLine - from.line + 1;
+ return {
+ changes,
+ newSelection
+ };
+};
+var deleteToStartOfLine = (editor, selection) => {
+ const pos = selection.head;
+ let startPos = getLineStartPos(pos.line);
+ if (pos.line === 0 && pos.ch === 0) {
+ return selection;
+ }
+ if (pos.line === startPos.line && pos.ch === startPos.ch) {
+ startPos = getLineEndPos(pos.line - 1, editor);
+ }
+ editor.replaceRange("", startPos, pos);
+ return {
+ anchor: startPos
+ };
+};
+var deleteToEndOfLine = (editor, selection) => {
+ const pos = selection.head;
+ let endPos = getLineEndPos(pos.line, editor);
+ if (pos.line === endPos.line && pos.ch === endPos.ch) {
+ endPos = getLineStartPos(pos.line + 1);
+ }
+ editor.replaceRange("", pos, endPos);
+ return {
+ anchor: pos
+ };
+};
+var joinLines = (editor, selection) => {
+ var _a, _b;
+ const { from, to } = getSelectionBoundaries(selection);
+ const { line } = from;
+ let endOfCurrentLine = getLineEndPos(line, editor);
+ const joinRangeLimit = Math.max(to.line - line, 1);
+ const selectionLength = editor.posToOffset(to) - editor.posToOffset(from);
+ let trimmedChars = "";
+ for (let i = 0; i < joinRangeLimit; i++) {
+ if (line === editor.lineCount() - 1) {
+ break;
+ }
+ endOfCurrentLine = getLineEndPos(line, editor);
+ const endOfNextLine = getLineEndPos(line + 1, editor);
+ const contentsOfCurrentLine = editor.getLine(line);
+ const contentsOfNextLine = editor.getLine(line + 1);
+ const charsToTrim = (_a = contentsOfNextLine.match(LIST_CHARACTER_REGEX)) != null ? _a : [];
+ trimmedChars += (_b = charsToTrim[0]) != null ? _b : "";
+ const newContentsOfNextLine = contentsOfNextLine.replace(LIST_CHARACTER_REGEX, "");
+ if (newContentsOfNextLine.length > 0 && contentsOfCurrentLine.charAt(endOfCurrentLine.ch - 1) !== " ") {
+ editor.replaceRange(" " + newContentsOfNextLine, endOfCurrentLine, endOfNextLine);
+ } else {
+ editor.replaceRange(newContentsOfNextLine, endOfCurrentLine, endOfNextLine);
+ }
+ }
+ if (selectionLength === 0) {
+ return {
+ anchor: endOfCurrentLine
+ };
+ }
+ return {
+ anchor: from,
+ head: {
+ line: from.line,
+ ch: from.ch + selectionLength - trimmedChars.length
+ }
+ };
+};
+var copyLine = (editor, selection, direction) => {
+ const { from, to, hasTrailingNewline } = getSelectionBoundaries(selection);
+ const fromLineStart = getLineStartPos(from.line);
+ const toLine = hasTrailingNewline ? to.line - 1 : to.line;
+ const toLineEnd = getLineEndPos(toLine, editor);
+ const contentsOfSelectedLines = editor.getRange(fromLineStart, toLineEnd);
+ if (direction === "up") {
+ editor.replaceRange("\n" + contentsOfSelectedLines, toLineEnd);
+ return selection;
+ } else {
+ editor.replaceRange(contentsOfSelectedLines + "\n", fromLineStart);
+ const linesSelected = to.line - from.line + 1;
+ return {
+ anchor: { line: toLine + 1, ch: from.ch },
+ head: { line: toLine + linesSelected, ch: to.ch }
+ };
+ }
+};
+var isManualSelection = true;
+var setIsManualSelection = (value) => {
+ isManualSelection = value;
+};
+var isProgrammaticSelectionChange = false;
+var setIsProgrammaticSelectionChange = (value) => {
+ isProgrammaticSelectionChange = value;
+};
+var selectWordOrNextOccurrence = (editor) => {
+ setIsProgrammaticSelectionChange(true);
+ const allSelections = editor.listSelections();
+ const { searchText, singleSearchText } = getSearchText({
+ editor,
+ allSelections,
+ autoExpand: false
+ });
+ if (searchText.length > 0 && singleSearchText) {
+ const { from: latestMatchPos } = getSelectionBoundaries(allSelections[allSelections.length - 1]);
+ const nextMatch = findNextMatchPosition({
+ editor,
+ latestMatchPos,
+ searchText,
+ searchWithinWords: isManualSelection,
+ documentContent: editor.getValue()
+ });
+ const newSelections = nextMatch ? allSelections.concat(nextMatch) : allSelections;
+ editor.setSelections(newSelections);
+ const lastSelection = newSelections[newSelections.length - 1];
+ editor.scrollIntoView(getSelectionBoundaries(lastSelection));
+ } else {
+ const newSelections = [];
+ for (const selection of allSelections) {
+ const { from, to } = getSelectionBoundaries(selection);
+ if (from.line !== to.line || from.ch !== to.ch) {
+ newSelections.push(selection);
+ } else {
+ newSelections.push(wordRangeAtPos(from, editor.getLine(from.line)));
+ setIsManualSelection(false);
+ }
+ }
+ editor.setSelections(newSelections);
+ }
+};
+var selectAllOccurrences = (editor) => {
+ const allSelections = editor.listSelections();
+ const { searchText, singleSearchText } = getSearchText({
+ editor,
+ allSelections,
+ autoExpand: true
+ });
+ if (!singleSearchText) {
+ return;
+ }
+ const matches = findAllMatchPositions({
+ editor,
+ searchText,
+ searchWithinWords: true,
+ documentContent: editor.getValue()
+ });
+ editor.setSelections(matches);
+};
+var selectLine = (_editor, selection) => {
+ const { from, to } = getSelectionBoundaries(selection);
+ const startOfCurrentLine = getLineStartPos(from.line);
+ const startOfNextLine = getLineStartPos(to.line + 1);
+ return { anchor: startOfCurrentLine, head: startOfNextLine };
+};
+var addCursorsToSelectionEnds = (editor, emulate = CODE_EDITOR.VSCODE) => {
+ if (editor.listSelections().length !== 1) {
+ return;
+ }
+ const selection = editor.listSelections()[0];
+ const { from, to, hasTrailingNewline } = getSelectionBoundaries(selection);
+ const newSelections = [];
+ const toLine = hasTrailingNewline ? to.line - 1 : to.line;
+ for (let line = from.line; line <= toLine; line++) {
+ const head = line === to.line ? to : getLineEndPos(line, editor);
+ let anchor;
+ if (emulate === CODE_EDITOR.VSCODE) {
+ anchor = head;
+ } else {
+ anchor = line === from.line ? from : getLineStartPos(line);
+ }
+ newSelections.push({
+ anchor,
+ head
+ });
+ }
+ editor.setSelections(newSelections);
+};
+var goToLineBoundary = (editor, selection, boundary) => {
+ const { from, to } = getSelectionBoundaries(selection);
+ if (boundary === "start") {
+ return { anchor: getLineStartPos(from.line) };
+ } else {
+ return { anchor: getLineEndPos(to.line, editor) };
+ }
+};
+var navigateLine = (editor, selection, position) => {
+ const pos = selection.head;
+ let line;
+ let ch;
+ if (position === "prev") {
+ line = Math.max(pos.line - 1, 0);
+ const endOfLine = getLineEndPos(line, editor);
+ ch = Math.min(pos.ch, endOfLine.ch);
+ }
+ if (position === "next") {
+ line = Math.min(pos.line + 1, editor.lineCount() - 1);
+ const endOfLine = getLineEndPos(line, editor);
+ ch = Math.min(pos.ch, endOfLine.ch);
+ }
+ if (position === "first") {
+ line = 0;
+ ch = 0;
+ }
+ if (position === "last") {
+ line = editor.lineCount() - 1;
+ const endOfLine = getLineEndPos(line, editor);
+ ch = endOfLine.ch;
+ }
+ return { anchor: { line, ch } };
+};
+var moveCursor = (editor, direction) => {
+ switch (direction) {
+ case "up":
+ editor.exec("goUp");
+ break;
+ case "down":
+ editor.exec("goDown");
+ break;
+ case "left":
+ editor.exec("goLeft");
+ break;
+ case "right":
+ editor.exec("goRight");
+ break;
+ }
+};
+var moveWord = (editor, direction) => {
+ switch (direction) {
+ case "left":
+ editor.exec("goWordLeft");
+ break;
+ case "right":
+ editor.exec("goWordRight");
+ break;
+ }
+};
+var transformCase = (editor, selection, caseType) => {
+ let { from, to } = getSelectionBoundaries(selection);
+ let selectedText = editor.getRange(from, to);
+ if (selectedText.length === 0) {
+ const pos = selection.head;
+ const { anchor, head } = wordRangeAtPos(pos, editor.getLine(pos.line));
+ [from, to] = [anchor, head];
+ selectedText = editor.getRange(anchor, head);
+ }
+ let replacementText = selectedText;
+ switch (caseType) {
+ case CASE.UPPER: {
+ replacementText = selectedText.toUpperCase();
+ break;
+ }
+ case CASE.LOWER: {
+ replacementText = selectedText.toLowerCase();
+ break;
+ }
+ case CASE.TITLE: {
+ replacementText = toTitleCase(selectedText);
+ break;
+ }
+ case CASE.NEXT: {
+ replacementText = getNextCase(selectedText);
+ break;
+ }
+ }
+ editor.replaceRange(replacementText, from, to);
+ return selection;
+};
+var expandSelection = ({
+ editor,
+ selection,
+ openingCharacterCheck,
+ matchingCharacterMap
+}) => {
+ let { anchor, head } = selection;
+ if (anchor.line >= head.line && anchor.ch > anchor.ch) {
+ [anchor, head] = [head, anchor];
+ }
+ const newAnchor = findPosOfNextCharacter({
+ editor,
+ startPos: anchor,
+ checkCharacter: openingCharacterCheck,
+ searchDirection: SEARCH_DIRECTION.BACKWARD
+ });
+ if (!newAnchor) {
+ return selection;
+ }
+ const newHead = findPosOfNextCharacter({
+ editor,
+ startPos: head,
+ checkCharacter: (char) => char === matchingCharacterMap[newAnchor.match],
+ searchDirection: SEARCH_DIRECTION.FORWARD
+ });
+ if (!newHead) {
+ return selection;
+ }
+ return { anchor: newAnchor.pos, head: newHead.pos };
+};
+var expandSelectionToBrackets = (editor, selection) => expandSelection({
+ editor,
+ selection,
+ openingCharacterCheck: (char) => /[([{]/.test(char),
+ matchingCharacterMap: MATCHING_BRACKETS
+});
+var expandSelectionToQuotes = (editor, selection) => expandSelection({
+ editor,
+ selection,
+ openingCharacterCheck: (char) => /['"`]/.test(char),
+ matchingCharacterMap: MATCHING_QUOTES
+});
+var expandSelectionToQuotesOrBrackets = (editor) => {
+ const selections = editor.listSelections();
+ const newSelection = expandSelection({
+ editor,
+ selection: selections[0],
+ openingCharacterCheck: (char) => /['"`([{]/.test(char),
+ matchingCharacterMap: MATCHING_QUOTES_BRACKETS
+ });
+ editor.setSelections([...selections, newSelection]);
+};
+var insertCursor = (editor, lineOffset) => {
+ const selections = editor.listSelections();
+ const newSelections = [];
+ for (const selection of selections) {
+ const { line, ch } = selection.head;
+ if (line === 0 && lineOffset < 0 || line === editor.lastLine() && lineOffset > 0) {
+ break;
+ }
+ const targetLineLength = editor.getLine(line + lineOffset).length;
+ newSelections.push({
+ anchor: {
+ line: selection.anchor.line + lineOffset,
+ ch: Math.min(selection.anchor.ch, targetLineLength)
+ },
+ head: {
+ line: line + lineOffset,
+ ch: Math.min(ch, targetLineLength)
+ }
+ });
+ }
+ editor.setSelections([...editor.listSelections(), ...newSelections]);
+};
+var insertCursorAbove = (editor) => insertCursor(editor, -1);
+var insertCursorBelow = (editor) => insertCursor(editor, 1);
+var goToHeading = (app, editor, boundary) => {
+ const file = app.metadataCache.getFileCache(app.workspace.getActiveFile());
+ if (!file.headings || file.headings.length === 0) {
+ return;
+ }
+ const { line } = editor.getCursor("from");
+ let prevHeadingLine = 0;
+ let nextHeadingLine = editor.lastLine();
+ file.headings.forEach(({ position }) => {
+ const { end: headingPos } = position;
+ if (line > headingPos.line && headingPos.line > prevHeadingLine) {
+ prevHeadingLine = headingPos.line;
+ }
+ if (line < headingPos.line && headingPos.line < nextHeadingLine) {
+ nextHeadingLine = headingPos.line;
+ }
+ });
+ editor.setSelection(boundary === "prev" ? getLineEndPos(prevHeadingLine, editor) : getLineEndPos(nextHeadingLine, editor));
+};
+
+// src/settings.ts
+var import_obsidian = __toModule(require("obsidian"));
+var DEFAULT_SETTINGS = {
+ autoInsertListPrefix: true
+};
+var SettingTab = class extends import_obsidian.PluginSettingTab {
+ constructor(app, plugin) {
+ super(app, plugin);
+ this.plugin = plugin;
+ }
+ display() {
+ const { containerEl } = this;
+ containerEl.empty();
+ containerEl.createEl("h2", { text: "Code Editor Shortcuts" });
+ const listPrefixSetting = new import_obsidian.Setting(containerEl).setName("Auto insert list prefix").setDesc("Automatically insert list prefix when inserting a line above or below").addToggle((toggle) => toggle.setValue(this.plugin.settings.autoInsertListPrefix).onChange((value) => __async(this, null, function* () {
+ this.plugin.settings.autoInsertListPrefix = value;
+ yield this.plugin.saveSettings();
+ })));
+ new import_obsidian.Setting(containerEl).setName("Reset defaults").addButton((btn) => {
+ btn.setButtonText("Reset").onClick(() => __async(this, null, function* () {
+ this.plugin.settings = __spreadValues({}, DEFAULT_SETTINGS);
+ listPrefixSetting.components[0].setValue(DEFAULT_SETTINGS.autoInsertListPrefix);
+ yield this.plugin.saveSettings();
+ }));
+ });
+ }
+};
+
+// src/modals.ts
+var import_obsidian2 = __toModule(require("obsidian"));
+var GoToLineModal = class extends import_obsidian2.SuggestModal {
+ constructor(app, lineCount, onSubmit) {
+ super(app);
+ this.lineCount = lineCount;
+ this.onSubmit = onSubmit;
+ const PROMPT_TEXT = `Enter a line number between 1 and ${lineCount}`;
+ this.limit = 1;
+ this.setPlaceholder(PROMPT_TEXT);
+ this.emptyStateText = PROMPT_TEXT;
+ }
+ getSuggestions(line) {
+ const lineNumber = parseInt(line);
+ if (line.length > 0 && lineNumber > 0 && lineNumber <= this.lineCount) {
+ return [line];
+ }
+ return [];
+ }
+ renderSuggestion(line, el) {
+ el.createEl("div", { text: line });
+ }
+ onChooseSuggestion(line) {
+ this.onSubmit(parseInt(line) - 1);
+ }
+};
+
+// src/main.ts
+var CodeEditorShortcuts = class extends import_obsidian3.Plugin {
+ onload() {
+ return __async(this, null, function* () {
+ yield this.loadSettings();
+ this.addCommand({
+ id: "insertLineAbove",
+ name: "Insert line above",
+ hotkeys: [
+ {
+ modifiers: ["Mod", "Shift"],
+ key: "Enter"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelectionsNew(editor, insertLineAbove)
+ });
+ this.addCommand({
+ id: "insertLineBelow",
+ name: "Insert line below",
+ hotkeys: [
+ {
+ modifiers: ["Mod"],
+ key: "Enter"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelectionsNew(editor, insertLineBelow)
+ });
+ this.addCommand({
+ id: "deleteLine",
+ name: "Delete line",
+ hotkeys: [
+ {
+ modifiers: ["Mod", "Shift"],
+ key: "K"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelectionsNew(editor, deleteLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ combineSameLineSelections: true
+ }))
+ });
+ this.addCommand({
+ id: "deleteToStartOfLine",
+ name: "Delete to start of line",
+ editorCallback: (editor) => withMultipleSelections(editor, deleteToStartOfLine)
+ });
+ this.addCommand({
+ id: "deleteToEndOfLine",
+ name: "Delete to end of line",
+ editorCallback: (editor) => withMultipleSelections(editor, deleteToEndOfLine)
+ });
+ this.addCommand({
+ id: "joinLines",
+ name: "Join lines",
+ hotkeys: [
+ {
+ modifiers: ["Mod"],
+ key: "J"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelections(editor, joinLines, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ repeatSameLineActions: false
+ }))
+ });
+ this.addCommand({
+ id: "duplicateLine",
+ name: "Duplicate line",
+ hotkeys: [
+ {
+ modifiers: ["Mod", "Shift"],
+ key: "D"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelections(editor, copyLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "down"
+ }))
+ });
+ this.addCommand({
+ id: "copyLineUp",
+ name: "Copy line up",
+ hotkeys: [
+ {
+ modifiers: ["Alt", "Shift"],
+ key: "ArrowUp"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelections(editor, copyLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "up"
+ }))
+ });
+ this.addCommand({
+ id: "copyLineDown",
+ name: "Copy line down",
+ hotkeys: [
+ {
+ modifiers: ["Alt", "Shift"],
+ key: "ArrowDown"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelections(editor, copyLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "down"
+ }))
+ });
+ this.addCommand({
+ id: "selectWordOrNextOccurrence",
+ name: "Select word or next occurrence",
+ hotkeys: [
+ {
+ modifiers: ["Mod"],
+ key: "D"
+ }
+ ],
+ editorCallback: (editor) => selectWordOrNextOccurrence(editor)
+ });
+ this.addCommand({
+ id: "selectAllOccurrences",
+ name: "Select all occurrences",
+ hotkeys: [
+ {
+ modifiers: ["Mod", "Shift"],
+ key: "L"
+ }
+ ],
+ editorCallback: (editor) => selectAllOccurrences(editor)
+ });
+ this.addCommand({
+ id: "selectLine",
+ name: "Select line",
+ hotkeys: [
+ {
+ modifiers: ["Mod"],
+ key: "L"
+ }
+ ],
+ editorCallback: (editor) => withMultipleSelections(editor, selectLine)
+ });
+ this.addCommand({
+ id: "addCursorsToSelectionEnds",
+ name: "Add cursors to selection ends",
+ hotkeys: [
+ {
+ modifiers: ["Alt", "Shift"],
+ key: "I"
+ }
+ ],
+ editorCallback: (editor) => addCursorsToSelectionEnds(editor)
+ });
+ this.addCommand({
+ id: "goToLineStart",
+ name: "Go to start of line",
+ editorCallback: (editor) => withMultipleSelections(editor, goToLineBoundary, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "start"
+ }))
+ });
+ this.addCommand({
+ id: "goToLineEnd",
+ name: "Go to end of line",
+ editorCallback: (editor) => withMultipleSelections(editor, goToLineBoundary, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "end"
+ }))
+ });
+ this.addCommand({
+ id: "goToNextLine",
+ name: "Go to next line",
+ editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "next"
+ }))
+ });
+ this.addCommand({
+ id: "goToPrevLine",
+ name: "Go to previous line",
+ editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "prev"
+ }))
+ });
+ this.addCommand({
+ id: "goToFirstLine",
+ name: "Go to first line",
+ editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "first"
+ }))
+ });
+ this.addCommand({
+ id: "goToLastLine",
+ name: "Go to last line",
+ editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: "last"
+ }))
+ });
+ this.addCommand({
+ id: "goToLineNumber",
+ name: "Go to line number",
+ editorCallback: (editor) => {
+ const lineCount = editor.lineCount();
+ const onSubmit = (line) => editor.setCursor({ line, ch: 0 });
+ new GoToLineModal(this.app, lineCount, onSubmit).open();
+ }
+ });
+ this.addCommand({
+ id: "goToNextChar",
+ name: "Move cursor forward",
+ editorCallback: (editor) => moveCursor(editor, "right")
+ });
+ this.addCommand({
+ id: "goToPrevChar",
+ name: "Move cursor backward",
+ editorCallback: (editor) => moveCursor(editor, "left")
+ });
+ this.addCommand({
+ id: "moveCursorUp",
+ name: "Move cursor up",
+ editorCallback: (editor) => moveCursor(editor, "up")
+ });
+ this.addCommand({
+ id: "moveCursorDown",
+ name: "Move cursor down",
+ editorCallback: (editor) => moveCursor(editor, "down")
+ });
+ this.addCommand({
+ id: "goToPreviousWord",
+ name: "Go to previous word",
+ editorCallback: (editor) => moveWord(editor, "left")
+ });
+ this.addCommand({
+ id: "goToNextWord",
+ name: "Go to next word",
+ editorCallback: (editor) => moveWord(editor, "right")
+ });
+ this.addCommand({
+ id: "transformToUppercase",
+ name: "Transform selection to uppercase",
+ editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: CASE.UPPER
+ }))
+ });
+ this.addCommand({
+ id: "transformToLowercase",
+ name: "Transform selection to lowercase",
+ editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: CASE.LOWER
+ }))
+ });
+ this.addCommand({
+ id: "transformToTitlecase",
+ name: "Transform selection to title case",
+ editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: CASE.TITLE
+ }))
+ });
+ this.addCommand({
+ id: "toggleCase",
+ name: "Toggle case of selection",
+ editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), {
+ args: CASE.NEXT
+ }))
+ });
+ this.addCommand({
+ id: "expandSelectionToBrackets",
+ name: "Expand selection to brackets",
+ editorCallback: (editor) => withMultipleSelections(editor, expandSelectionToBrackets)
+ });
+ this.addCommand({
+ id: "expandSelectionToQuotes",
+ name: "Expand selection to quotes",
+ editorCallback: (editor) => withMultipleSelections(editor, expandSelectionToQuotes)
+ });
+ this.addCommand({
+ id: "expandSelectionToQuotesOrBrackets",
+ name: "Expand selection to quotes or brackets",
+ editorCallback: (editor) => expandSelectionToQuotesOrBrackets(editor)
+ });
+ this.addCommand({
+ id: "insertCursorAbove",
+ name: "Insert cursor above",
+ editorCallback: (editor) => insertCursorAbove(editor)
+ });
+ this.addCommand({
+ id: "insertCursorBelow",
+ name: "Insert cursor below",
+ editorCallback: (editor) => insertCursorBelow(editor)
+ });
+ this.addCommand({
+ id: "goToNextHeading",
+ name: "Go to next heading",
+ editorCallback: (editor) => goToHeading(this.app, editor, "next")
+ });
+ this.addCommand({
+ id: "goToPrevHeading",
+ name: "Go to previous heading",
+ editorCallback: (editor) => goToHeading(this.app, editor, "prev")
+ });
+ this.addCommand({
+ id: "toggle-line-numbers",
+ name: "Toggle line numbers",
+ callback: () => toggleVaultConfig(this.app, "showLineNumber")
+ });
+ this.addCommand({
+ id: "indent-using-tabs",
+ name: "Indent using tabs",
+ callback: () => setVaultConfig(this.app, "useTab", true)
+ });
+ this.addCommand({
+ id: "indent-using-spaces",
+ name: "Indent using spaces",
+ callback: () => setVaultConfig(this.app, "useTab", false)
+ });
+ this.addCommand({
+ id: "undo",
+ name: "Undo",
+ editorCallback: (editor) => editor.undo()
+ });
+ this.addCommand({
+ id: "redo",
+ name: "Redo",
+ editorCallback: (editor) => editor.redo()
+ });
+ this.registerSelectionChangeListeners();
+ this.addSettingTab(new SettingTab(this.app, this));
+ });
+ }
+ registerSelectionChangeListeners() {
+ this.app.workspace.onLayoutReady(() => {
+ const handleSelectionChange = (evt) => {
+ if (evt instanceof KeyboardEvent && MODIFIER_KEYS.includes(evt.key)) {
+ return;
+ }
+ if (!isProgrammaticSelectionChange) {
+ setIsManualSelection(true);
+ }
+ setIsProgrammaticSelectionChange(false);
+ };
+ iterateCodeMirrorDivs((cm) => {
+ this.registerDomEvent(cm, "keydown", handleSelectionChange);
+ this.registerDomEvent(cm, "click", handleSelectionChange);
+ this.registerDomEvent(cm, "dblclick", handleSelectionChange);
+ });
+ });
+ }
+ loadSettings() {
+ return __async(this, null, function* () {
+ const savedSettings = yield this.loadData();
+ this.settings = __spreadValues(__spreadValues({}, DEFAULT_SETTINGS), savedSettings);
+ SettingsState.autoInsertListPrefix = this.settings.autoInsertListPrefix;
+ });
+ }
+ saveSettings() {
+ return __async(this, null, function* () {
+ yield this.saveData(this.settings);
+ SettingsState.autoInsertListPrefix = this.settings.autoInsertListPrefix;
+ });
+ }
+};