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;
    });
  }
};
