Files
kte/default.nix
T
Claude e782d24e32 Regex: optional PCRE2 engine behind kte::Regex
RegexEngine.h/.cc wrap the regex engine for search, regex replace-all and
the terminal and ImGui renderers' match highlighting:

- With KTE_USE_PCRE2 (default ON; used when pkg-config finds libpcre2-8,
  linked as -lpcre2-8) patterns are compiled by PCRE2 with its JIT and
  matched under a match limit: catastrophic backtracking stops with a
  status note instead of hanging the editor, and matching does not
  recurse on the C stack (no large-stack thread; the per-keystroke and
  per-frame line limit is 1 MiB instead of 2,000 bytes). Otherwise
  std::regex is used as before.
- Replacement strings follow std::regex_replace (ECMAScript as libstdc++
  reads it) with either engine: the PCRE2 path expands $&, $n, $`, $',
  $$ itself and steps over empty matches the same way.
- Regex search walks lines over the materialized text instead of calling
  GetLineView per row. The terminal renderer compiles the pattern once
  per frame (it compiled it for every row).
- Only one checkpoint per journal is queued at a time: whole-file edits
  in a row on a large buffer each queued a full copy of the buffer.
- default.nix and the Dockerfile add pcre2 and pkg-config.

On 26 MB: regex keystroke 1.6 -> 0.14 ms, next 62 -> 6 ms, replace-all
929 -> 438 ms; a rarely matching regex over 105 MB: 1.55 s -> 0.10 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
2026-09-24 09:16:04 -07:00

114 lines
2.7 KiB
Nix

{
lib,
stdenv,
cmake,
pkg-config,
ncurses,
pcre2,
SDL2,
libGL,
xorg,
kdePackages,
qt6Packages ? kdePackages.qt6Packages,
installShellFiles,
copyDesktopItems,
makeDesktopItem,
graphical ? false,
graphical-qt ? false,
}:
let
cmakeContent = builtins.readFile ./CMakeLists.txt;
cmakeLines = lib.splitString "\n" cmakeContent;
versionLine = lib.findFirst (
l: builtins.match ".*set\\(KTE_VERSION \".+\"\\).*" l != null
) (throw "KTE_VERSION not found in CMakeLists.txt") cmakeLines;
version = builtins.head (builtins.match ".*set\\(KTE_VERSION \"(.+)\"\\).*" versionLine);
in
stdenv.mkDerivation {
pname = if graphical then (if graphical-qt then "kge-qt" else "kge") else "kte";
inherit version;
src = lib.cleanSource ./.;
nativeBuildInputs = [
cmake
pkg-config
installShellFiles
] ++ lib.optionals graphical [
copyDesktopItems
] ++ lib.optionals graphical-qt [
qt6Packages.wrapQtAppsHook
];
buildInputs = [
ncurses
pcre2 # regex engine (optional; std::regex without it)
] ++ lib.optionals graphical [
SDL2
libGL
xorg.libX11
] ++ lib.optionals graphical-qt [
kdePackages.qt6ct
qt6Packages.qtbase
];
cmakeFlags = [
"-DBUILD_GUI=${if graphical then "ON" else "OFF"}"
"-DKTE_USE_QT=${if graphical-qt then "ON" else "OFF"}"
"-DCMAKE_BUILD_TYPE=Debug"
"-DKTE_STATIC_LINK=OFF"
];
desktopItems = lib.optionals graphical [
(makeDesktopItem {
name = "kge";
desktopName = "kge";
genericName = "Text Editor";
comment = "kyle's graphical text editor";
exec = if graphical-qt then "kge-qt %F" else "kge %F";
icon = "kge";
terminal = false;
categories = [ "Utility" "TextEditor" "Development" ];
mimeTypes = [
"text/plain"
"text/x-c"
"text/x-c++"
"text/x-python"
"text/x-go"
"text/x-rust"
"application/json"
"text/markdown"
"text/x-shellscript"
];
})
];
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp kte $out/bin/
installManPage ../docs/kte.1
${lib.optionalString graphical ''
${if graphical-qt then ''
cp kge $out/bin/kge-qt
'' else ''
cp kge $out/bin/kge
''}
installManPage ../docs/kge.1
mkdir -p $out/share/icons/hicolor/256x256/apps
cp ../kge.png $out/share/icons/hicolor/256x256/apps/kge.png
''}
runHook postInstall
'';
meta = {
description = "kyle's text editor" + lib.optionalString graphical " (graphical)";
platforms = lib.platforms.unix;
mainProgram = if graphical then (if graphical-qt then "kge-qt" else "kge") else "kte";
};
}