var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  activate: () => activate
});
module.exports = __toCommonJS(index_exports);
var import_coc2 = require("coc.nvim");

// src/util.ts
var import_coc = require("coc.nvim");
function isWord(character, bufnr) {
  let doc = import_coc.workspace.getDocument(bufnr);
  if (doc && doc.attached) return doc.isWord(character);
  let code = character.charCodeAt(0);
  if (code > 128) return false;
  if (code == 95) return true;
  if (code >= 48 && code <= 57) return true;
  if (code >= 65 && code <= 90) return true;
  if (code >= 97 && code <= 122) return true;
  return false;
}
var UTF8_2BYTES_START = 128;
var UTF8_3BYTES_START = 2048;
var UTF8_4BYTES_START = 65536;
function characterIndex(content, byteIndex) {
  if (byteIndex == 0) return 0;
  let characterIndex2 = 0;
  let total = 0;
  for (let codePoint of content) {
    let code = codePoint.codePointAt(0) ?? 0;
    if (code >= UTF8_4BYTES_START) {
      characterIndex2 += 2;
      total += 4;
    } else {
      characterIndex2 += 1;
      total += utf8_code2len(code);
    }
    if (total >= byteIndex) break;
  }
  return characterIndex2;
}
function utf8_code2len(code) {
  if (code < UTF8_2BYTES_START) return 1;
  if (code < UTF8_3BYTES_START) return 2;
  if (code < UTF8_4BYTES_START) return 3;
  return 4;
}

// src/index.ts
var pairs = /* @__PURE__ */ new Map();
pairs.set("{", "}");
pairs.set("[", "]");
pairs.set("(", ")");
pairs.set("<", ">");
pairs.set('"', '"');
pairs.set("'", "'");
pairs.set("`", "`");
pairs.set("\u3010", "\u3011");
pairs.set("\u300C", "\u300D");
pairs.set("\u300A", "\u300B");
pairs.set("\u300E", "\u300F");
var insertMaps = /* @__PURE__ */ new Map();
var allowedQuotePrefixes = /* @__PURE__ */ new Map();
allowedQuotePrefixes.set("python", ["b", "r", "f", "u"]);
function checkAllow(filetype, character, pre) {
  if (character !== "'" && character !== '"') return false;
  let prefixes = allowedQuotePrefixes.get(filetype);
  if (!prefixes) return false;
  let char = (pre[pre.length - 1] ?? "").toLowerCase();
  return prefixes.includes(char);
}
function removeLast(bufnr) {
  let insert = insertMaps.get(bufnr);
  if (!insert) return;
  insert.pairs.pop();
  if (insert.pairs.length == 0) {
    insertMaps.delete(bufnr);
  }
}
function shouldRemove(insert, index) {
  if (!insert) return false;
  let { pairs: pairs2 } = insert;
  let last = pairs2[pairs2.length - 1];
  if (!last) return false;
  return last.position.character + last.inserted.length === index;
}
function onCursorMove(bufnr, cursor) {
  let currentInsert = insertMaps.get(bufnr);
  if (!currentInsert) return;
  if (currentInsert.bufnr != bufnr || currentInsert.lnum !== cursor[0]) return;
  let { pairs: pairs2 } = currentInsert;
  let doc = import_coc2.workspace.getDocument(bufnr);
  if (!doc || !doc.attached) return;
  let line = doc.getline(cursor[0] - 1);
  let index = characterIndex(line, cursor[1] - 1);
  let last = pairs2[pairs2.length - 1];
  if (!last || last.position.character > index) {
    insertMaps.delete(bufnr);
  }
}
async function activate(context) {
  let { subscriptions } = context;
  const config = import_coc2.workspace.getConfiguration("pairs");
  const disableLanguages = config.inspect("disableLanguages").globalValue ?? [];
  const characters = config.get("enableCharacters");
  const alwaysPairCharacters = config.inspect("alwaysPairCharacters").globalValue ?? [];
  const enableBackspace = config.inspect("enableBackspace").globalValue ?? true;
  const disableBuftypes = config.inspect("disableBuftypes").globalValue ?? [];
  const eolCharacters = config.inspect("requireEOLCharacters").globalValue ?? [];
  subscriptions.push(import_coc2.events.on("BufUnload", (bufnr) => {
    insertMaps.delete(bufnr);
  }));
  subscriptions.push(import_coc2.events.on("CursorMovedI", onCursorMove));
  const { nvim, isVim } = import_coc2.workspace;
  const localParis = /* @__PURE__ */ new Map();
  async function onBackspace() {
    let { nvim: nvim2 } = import_coc2.workspace;
    let res = await nvim2.eval('[getline("."),col("."),synIDattr(synID(line("."), col(".") - 2, 1), "name"),bufnr("%")]');
    if (res) {
      let [line, col, synname, bufnr] = res;
      if (col > 1 && !/string/i.test(synname)) {
        let buf = Buffer.from(line, "utf8");
        if (col - 1 < buf.length) {
          let previous = buf.subarray(0, col - 1).toString("utf8");
          let pre = previous[previous.length - 1] ?? "";
          let next = line[previous.length] ?? "";
          let local = localParis.get(bufnr);
          if (local && local.find((arr) => arr[0] == pre && arr[1] == next)) {
            await nvim2.eval(`feedkeys("\\<C-G>U\\<right>\\<bs>\\<bs>", 'in')`);
            if (isVim) nvim2.command("redraw", true);
            return;
          }
          let idx = characterIndex(line, col - 1);
          let currentInsert = insertMaps.get(bufnr);
          if (shouldRemove(currentInsert, idx) && characters.includes(pre) && pairs.get(pre) == next) {
            removeLast(bufnr);
            await nvim2.eval(`feedkeys("\\<C-G>U\\<right>\\<bs>\\<bs>", 'in')`);
            if (isVim) nvim2.command("redraw", true);
            return;
          }
        }
      }
    }
    await nvim2.eval(`feedkeys("\\<bs>", 'in')`);
    if (isVim) nvim2.command("redraw", true);
    return "";
  }
  async function insertPair(character, pair) {
    let samePair = character == pair;
    let arr = await nvim.eval(`[bufnr("%"),get(b:,"coc_pairs_disabled",[]),coc#util#cursor(),&filetype,getline("."),mode(),get(get(g:,'context_filetype#filetypes',{}),&filetype,v:null),&buftype]`);
    let filetype = arr[3];
    let buftype = arr[7] ?? "";
    if (disableLanguages.includes(filetype) || disableBuftypes.includes(buftype)) return character;
    let bufnr = arr[0];
    let line = arr[4];
    let mode = arr[5];
    if (mode.startsWith("R")) return character;
    let chars = arr[1];
    let context2 = arr[6];
    if (chars && chars.length && chars.indexOf(character) !== -1) return character;
    let pos = { line: arr[2][0], character: arr[2][1] };
    if (eolCharacters.includes(character) && line.length !== pos.character) return character;
    let currentInsert = insertMaps.get(bufnr);
    if (currentInsert && currentInsert.lnum != pos.line + 1) {
      currentInsert = void 0;
    }
    let pre = line.slice(0, pos.character);
    let rest = line.slice(pos.character);
    let previous = pre.length ? pre[pre.length - 1] : "";
    if (alwaysPairCharacters.indexOf(character) == -1 && rest && isWord(rest[0], bufnr)) return character;
    if (character == "<" && (previous == " " || previous == "<")) {
      return character;
    }
    if (samePair && rest[0] == character && rest[1] != character) {
      await nvim.eval(`feedkeys("\\<C-G>U\\<Right>", 'in')`);
      return "";
    }
    let skipByWord = !checkAllow(filetype, character, pre) && isWord(previous, bufnr);
    if (samePair && pre.length && (previous == character || skipByWord)) return character;
    if (character === "'" && pre.match(/.*\w$/)) {
      return character;
    }
    if (context2) {
      try {
        let res = await nvim.call("context_filetype#get");
        if (res && res.filetype) {
          filetype = res.filetype;
        }
      } catch (e) {
      }
    }
    if (filetype === "rust" && character === "'" && (pre.endsWith("<") || rest.startsWith(">") || pre.endsWith("&"))) {
      return character;
    }
    if ((filetype === "vim" || filetype === "help") && character === '"' && pos.character === 0) {
      return character;
    }
    if (samePair && pre.length >= 2 && previous == character && pre[pre.length - 2] == character) {
      if (pre[pre.length - 3] == character) {
        if (character == '"') {
          nvim.command(`call feedkeys('"""'."${"\\<C-G>U\\<Left>".repeat(3)}", 'in')`, true);
        } else {
          nvim.command(`call feedkeys("${character.repeat(3)}${"\\<C-G>U\\<Left>".repeat(3)}", 'in')`, true);
        }
        return;
      }
      return character;
    }
    if (character == '"') {
      nvim.command(`call feedkeys('""'."\\<C-G>U\\<Left>", 'in')`, true);
    } else {
      nvim.command(`call feedkeys("${character}${pair}${"\\<C-G>U\\<Left>".repeat(pair.length)}", 'in')`, true);
    }
    if (!currentInsert) currentInsert = { bufnr, lnum: pos.line + 1, pairs: [] };
    currentInsert.pairs.push({ inserted: character, paired: pair, position: pos });
    insertMaps.set(bufnr, currentInsert);
    return "";
  }
  async function closePair(character) {
    let [bufnr, cursor, filetype, line] = await nvim.eval('[bufnr("%"),coc#util#cursor(),&filetype,getline(".")]');
    let rest = line.slice(cursor[1]);
    let currentInsert = insertMaps.get(bufnr);
    if (!currentInsert || rest[0] !== character || disableLanguages.includes(filetype)) return character;
    let item = currentInsert.pairs.find((o) => o.paired === character);
    if (!item) return character;
    let prev = item.inserted;
    if (prev !== character) {
      let n = 0;
      for (let i = 0; i < line.length; i++) {
        if (line[i] === prev) {
          n++;
        } else if (line[i] === character) {
          n--;
        }
      }
      if (n > 0) return character;
    }
    nvim.command(`call feedkeys("\\<C-G>U\\<Right>", 'in')`, true);
    return "";
  }
  nvim.pauseNotification();
  for (let character of characters) {
    if (!pairs.has(character)) continue;
    subscriptions.push(
      import_coc2.workspace.registerExprKeymap("i", character, insertPair.bind(null, character, pairs.get(character)), false)
    );
    let matched = pairs.get(character);
    if (matched != character) {
      subscriptions.push(import_coc2.workspace.registerExprKeymap("i", matched, closePair.bind(null, matched), false));
    }
  }
  if (enableBackspace) {
    subscriptions.push(import_coc2.workspace.registerExprKeymap("i", "<bs>", onBackspace, false, false));
  }
  nvim.resumeNotification(false, true);
  async function createBufferKeymap(doc) {
    if (!doc) return;
    let pairs2 = doc.getVar("pairs", null);
    if (!pairs2 || !pairs2.length) return;
    localParis.set(doc.bufnr, pairs2);
    let bufnr = doc.bufnr;
    nvim.pauseNotification();
    for (let p of pairs2) {
      if (Array.isArray(p) && p.length == 2) {
        let [character, matched] = p;
        subscriptions.push(
          import_coc2.workspace.registerExprKeymap("i", character, insertPair.bind(null, character, matched), bufnr)
        );
        if (matched != character) {
          subscriptions.push(import_coc2.workspace.registerExprKeymap("i", matched, closePair.bind(null, matched), bufnr));
        }
      }
    }
    nvim.resumeNotification(false, true);
  }
  import_coc2.workspace.documents.forEach((doc) => {
    createBufferKeymap(doc);
  });
  import_coc2.workspace.onDidOpenTextDocument(async (e) => {
    await createBufferKeymap(import_coc2.workspace.getDocument(e.uri));
  });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  activate
});
