"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var textUtils_exports = {};
__export(textUtils_exports, {
  clearStringWidthCache: () => clearStringWidthCache,
  cpLen: () => cpLen,
  cpSlice: () => cpSlice,
  findNextWordBoundary: () => findNextWordBoundary,
  findNextWordStartInLine: () => findNextWordStartInLine,
  findPrevWordBoundary: () => findPrevWordBoundary,
  findPrevWordStartInLine: () => findPrevWordStartInLine,
  getCachedStringWidth: () => getCachedStringWidth,
  getCharScript: () => getCharScript,
  isCombiningMark: () => isCombiningMark,
  isDifferentScript: () => isDifferentScript,
  isWhitespace: () => isWhitespace,
  isWordCharStrict: () => isWordCharStrict,
  isWordCharWithCombining: () => isWordCharWithCombining,
  stripUnsafeCharacters: () => stripUnsafeCharacters,
  toCodePoints: () => toCodePoints
});
module.exports = __toCommonJS(textUtils_exports);
var import_strip_ansi = __toESM(require("strip-ansi"), 1);
var import_string_width = __toESM(require("string-width"), 1);
const codePointsCache = /* @__PURE__ */ new Map();
const MAX_STRING_LENGTH_TO_CACHE = 1e3;
function toCodePoints(str) {
  let isAscii = true;
  for (let i = 0; i < str.length; i++) {
    if (str.charCodeAt(i) > 127) {
      isAscii = false;
      break;
    }
  }
  if (isAscii) {
    return str.split("");
  }
  if (str.length <= MAX_STRING_LENGTH_TO_CACHE) {
    const cached = codePointsCache.get(str);
    if (cached) {
      return [...cached];
    }
  }
  const result = Array.from(str);
  if (str.length <= MAX_STRING_LENGTH_TO_CACHE) {
    codePointsCache.set(str, result);
  }
  return result;
}
function cpLen(str) {
  return toCodePoints(str).length;
}
function cpSlice(str, start, end) {
  const arr = toCodePoints(str).slice(start, end);
  return arr.join("");
}
function stripUnsafeCharacters(str) {
  const strippedAnsi = (0, import_strip_ansi.default)(str);
  return toCodePoints(strippedAnsi).filter((char) => {
    const code = char.codePointAt(0);
    if (code === void 0) return false;
    if (code === 10 || code === 13 || code === 9) return true;
    if (code >= 0 && code <= 31) return false;
    if (code === 127) return false;
    if (code >= 128 && code <= 159) return false;
    return true;
  }).join("");
}
const stringWidthCache = /* @__PURE__ */ new Map();
function getCachedStringWidth(str) {
  if (/^[\x20-\x7E]*$/.test(str)) {
    return str.length;
  }
  if (stringWidthCache.has(str)) {
    return stringWidthCache.get(str);
  }
  const width = (0, import_string_width.default)(str);
  stringWidthCache.set(str, width);
  return width;
}
function clearStringWidthCache() {
  stringWidthCache.clear();
}
const isWordCharStrict = (char) => char !== void 0 && /[\w\p{L}\p{N}]/u.test(char);
const isWhitespace = (char) => char !== void 0 && /\s/.test(char);
const isCombiningMark = (char) => char !== void 0 && /\p{M}/u.test(char);
const isWordCharWithCombining = (char) => isWordCharStrict(char) || isCombiningMark(char);
const getCharScript = (char) => {
  if (!char) return "other";
  if (/[\p{Script=Latin}]/u.test(char)) return "latin";
  if (/[\p{Script=Han}]/u.test(char)) return "han";
  if (/[\p{Script=Arabic}]/u.test(char)) return "arabic";
  if (/[\p{Script=Hiragana}]/u.test(char)) return "hiragana";
  if (/[\p{Script=Katakana}]/u.test(char)) return "katakana";
  if (/[\p{Script=Cyrillic}]/u.test(char)) return "cyrillic";
  return "other";
};
const isDifferentScript = (char1, char2) => {
  if (!isWordCharStrict(char1) || !isWordCharStrict(char2)) return false;
  return getCharScript(char1) !== getCharScript(char2);
};
const segmenter = new Intl.Segmenter(void 0, { granularity: "word" });
function findPrevWordBoundary(line, cursorCol) {
  const codePoints = toCodePoints(line);
  const prefix = codePoints.slice(0, cursorCol).join("");
  const cursorIdx = prefix.length;
  let targetIdx = 0;
  for (const seg of segmenter.segment(line)) {
    if (seg.index >= cursorIdx) break;
    if (seg.isWordLike) {
      targetIdx = seg.index;
    }
  }
  return toCodePoints(line.slice(0, targetIdx)).length;
}
function findNextWordBoundary(line, cursorCol) {
  const codePoints = toCodePoints(line);
  const prefix = codePoints.slice(0, cursorCol).join("");
  const cursorIdx = prefix.length;
  let targetIdx = line.length;
  for (const seg of segmenter.segment(line)) {
    const segEnd = seg.index + seg.segment.length;
    if (segEnd > cursorIdx) {
      if (seg.isWordLike) {
        targetIdx = segEnd;
        break;
      }
    }
  }
  return toCodePoints(line.slice(0, targetIdx)).length;
}
function findNextWordStartInLine(line, col) {
  const chars = toCodePoints(line);
  let i = col;
  if (i >= chars.length) return null;
  const currentChar = chars[i];
  if (isWordCharStrict(currentChar)) {
    while (i < chars.length && isWordCharWithCombining(chars[i])) {
      if (i + 1 < chars.length && isWordCharStrict(chars[i + 1]) && isDifferentScript(chars[i], chars[i + 1])) {
        i++;
        break;
      }
      i++;
    }
  } else if (!isWhitespace(currentChar)) {
    while (i < chars.length && !isWordCharStrict(chars[i]) && !isWhitespace(chars[i])) {
      i++;
    }
  }
  while (i < chars.length && isWhitespace(chars[i])) {
    i++;
  }
  return i < chars.length ? i : null;
}
function findPrevWordStartInLine(line, col) {
  const chars = toCodePoints(line);
  let i = col;
  if (i <= 0) return null;
  i--;
  while (i >= 0 && isWhitespace(chars[i])) {
    i--;
  }
  if (i < 0) return null;
  if (isWordCharStrict(chars[i])) {
    while (i >= 0 && isWordCharStrict(chars[i])) {
      if (i - 1 >= 0 && isWordCharStrict(chars[i - 1]) && isDifferentScript(chars[i], chars[i - 1])) {
        return i;
      }
      i--;
    }
    return i + 1;
  } else {
    while (i >= 0 && !isWordCharStrict(chars[i]) && !isWhitespace(chars[i])) {
      i--;
    }
    return i + 1;
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  clearStringWidthCache,
  cpLen,
  cpSlice,
  findNextWordBoundary,
  findNextWordStartInLine,
  findPrevWordBoundary,
  findPrevWordStartInLine,
  getCachedStringWidth,
  getCharScript,
  isCombiningMark,
  isDifferentScript,
  isWhitespace,
  isWordCharStrict,
  isWordCharWithCombining,
  stripUnsafeCharacters,
  toCodePoints
});
