[{"data":1,"prerenderedAt":393},["ShallowReactive",2],{"seite-\u002Fopen-source\u002Feditor-suche\u002F":3},{"id":4,"title":5,"body":6,"description":384,"extension":385,"meta":386,"navigation":387,"path":388,"robots":389,"seo":390,"stem":391,"__hash__":392},"seiten\u002Fopen-source\u002Feditor-suche.md","Sieben Monate auf der Suche nach einem Editor",{"type":7,"value":8,"toc":375},"minimark",[9,13,17,20,25,28,31,35,38,58,72,76,79,82,86,89,242,246,253,260,271,275,280,291,297,344,351,354,361,364,368,371],[10,11,5],"h1",{"id":12},"sieben-monate-auf-der-suche-nach-einem-editor",[14,15,16],"p",{},"VS Code war mein erster und einziger Editor. Doch die Leistung störte mich:\nmanchmal verbraucht er unheimlich viel Prozessor und Arbeitsspeicher. Also habe\nich angefangen, nach etwas Schnellerem zu suchen.",[14,18,19],{},"Meine Anforderungen waren überschaubar: Vorschau für PDF und Bilder, ein\nTerminal, und Git im Editor.",[21,22,24],"h2",{"id":23},"terminal-editoren-sind-schnell-aber-blind","Terminal-Editoren sind schnell, aber blind",[14,26,27],{},"Der erste Weg führte in den Terminal. Dort ist die Geschwindigkeit kein\nProblem. Die Vorschau schon: kein Bild, kein PDF, kein gerendertes Markdown.",[14,29,30],{},"Also habe ich versucht, es nachzurüsten. Bei Fresh sind die Plugins dafür zu\neingeschränkt. Bei LazyVim funktioniert es, aber nicht überall. Nicht jedes\nTerminal spielt mit, stabil genug war es auch nicht, und über allem stand die\nAhnung, dass ich irgendwann doch an eine Decke stosse, die im Terminal\neingebaut ist.",[21,32,34],{"id":33},"die-hülle-tauschen-statt-das-plugin-flicken","Die Hülle tauschen statt das Plugin flicken",[14,36,37],{},"Daraus wurde der erste eigene Ansatz, und er kehrt die Aufgabe um. Wenn die\nVorschau nicht in den Terminal passt, dann muss der Terminal-Editor eben in\nein Fenster.",[14,39,40,41,45,46,49,50,53,54,57],{},"Zwei Versuche gingen in diese Richtung. ",[42,43,44],"code",{},"neoview"," bettet Neovim über ",[42,47,48],{},"nvim-rs","\nin eine Oberfläche aus gpui ein, dem Framework, mit dem auch Zed gebaut ist.\nDie Oberfläche redet dabei über msgpack-rpc mit Neovim. ",[42,51,52],{},"freshview"," macht\ndasselbe mit dem Editor Fresh, nur enger: Fresh läuft als Bibliothek im selben\nProzess, egui liefert das Fenster, ",[42,55,56],{},"egui_ratatui"," übersetzt dazwischen, und\nmupdf zeichnet PDF und Bilder in schwebende Fenster daneben.",[14,59,60,61,64,65,68,69,71],{},"Die nächsten Anläufe, ",[42,62,63],{},"flexed"," und ",[42,66,67],{},"editor-framework",", sind keine Wrapper\nmehr, sondern Gerüste auf gpui, in denen nichts Kern ist und alles Plugin.\nBei ",[42,70,67],{}," sind die Plugins in Lua und lassen sich ohne Neubau\nnachladen.",[21,73,75],{"id":74},"warum-rust-wegfiel","Warum Rust wegfiel",[14,77,78],{},"Rust war mir zu langsam im Bauen. Und gpui ist Rust, also fiel es mit.",[14,80,81],{},"Gesucht war eine andere schnelle Sprache, mit der sich Zed Konkurrenz machen\nlässt. Go wirkte verstaubt, V zu wenig bekannt, und Zig stand gerade im\nDurchbruch als Konkurrent zu Rust. Also Zig.",[21,83,85],{"id":84},"dreizehn-anläufe-neun-oberflächen","Dreizehn Anläufe, neun Oberflächen",[14,87,88],{},"Jede Zeile ist ein eigenes Repo, in der Reihenfolge, in der sie entstanden\nsind. Manche haben einen Tag gelebt, manche eine Woche.",[90,91,92,108],"table",{},[93,94,95],"thead",{},[96,97,98,102,105],"tr",{},[99,100,101],"th",{},"Anlauf",[99,103,104],{},"Sprache",[99,106,107],{},"Oberfläche",[109,110,111,122,131,139,148,158,169,180,191,202,212,222,232],"tbody",{},[96,112,113,116,119],{},[114,115,44],"td",{},[114,117,118],{},"Rust",[114,120,121],{},"gpui",[96,123,124,126,128],{},[114,125,52],{},[114,127,118],{},[114,129,130],{},"egui, egui_ratatui",[96,132,133,135,137],{},[114,134,63],{},[114,136,118],{},[114,138,121],{},[96,140,141,143,145],{},[114,142,67],{},[114,144,118],{},[114,146,147],{},"gpui, mlua",[96,149,150,153,155],{},[114,151,152],{},"slint-rust-editor",[114,154,118],{},[114,156,157],{},"Slint",[96,159,160,163,166],{},[114,161,162],{},"mojo-nuklear-editor",[114,164,165],{},"Mojo, C-Brücke",[114,167,168],{},"Nuklear",[96,170,171,174,177],{},[114,172,173],{},"slint-editor",[114,175,176],{},"Mojo",[114,178,179],{},"Slint über Python",[96,181,182,185,188],{},[114,183,184],{},"v-gui-editor",[114,186,187],{},"V",[114,189,190],{},"GUI-Framework von V",[96,192,193,196,199],{},[114,194,195],{},"sokol-zig-editor",[114,197,198],{},"Zig",[114,200,201],{},"sokol, Dear ImGui",[96,203,204,207,209],{},[114,205,206],{},"zed-clone",[114,208,198],{},[114,210,211],{},"dvui",[96,213,214,217,219],{},[114,215,216],{},"sokol-nanovg-zig-editor",[114,218,198],{},[114,220,221],{},"sokol, NanoVG",[96,223,224,227,229],{},[114,225,226],{},"qt-ziged",[114,228,198],{},[114,230,231],{},"Qt 6 über libqt6zig",[96,233,234,237,239],{},[114,235,236],{},"zed-killer",[114,238,198],{},[114,240,241],{},"gooey",[21,243,245],{"id":244},"was-daraus-wurde","Was daraus wurde",[14,247,248,249,252],{},"Der Editor heisst ",[42,250,251],{},"zid"," und ist in Zig geschrieben. Er zeichnet über wgpu,\nim Renderer auf das Vulkan-Backend festgelegt. Das Layout macht Clay. Die\nTextdarstellung ist eigen: Glyphen-Atlas und GPU-Renderer über FreeType.",[14,254,255,256,259],{},"Der Editor selbst ist eigen: Eingabe, Bearbeitungsbefehle, Suche,\nZeilenumbruch, Zeilennummern, Tastenbelegung. Darunter liegt Fremdes, und\nzwar bewusst. Die Textspeicherung übernimmt ",[42,257,258],{},"flow-core",", die Kernbibliothek\ndes Editors Flow Control, mit Puffer, Cursor- und Auswahltypen. Die\nSyntaxhervorhebung kommt aus demselben Haus über tree-sitter. Das Terminal\nist die Emulation von Ghostty, Markdown rendert zigdown, PDF zeichnet mupdf.",[14,261,262,263,64,265,267,268,270],{},"Das ist ein anderer Schnitt als bei ",[42,264,44],{},[42,266,52],{},". Dort war der\nganze Editor fremd und nur die Hülle eigen. Bei ",[42,269,251],{}," ist es umgekehrt: der\nEditor ist eigen, fremd sind die Bausteine darunter, die nichts mit dem\nEditieren zu tun haben.",[21,272,274],{"id":273},"regeln-gehören-in-den-code-nicht-in-den-prompt","Regeln gehören in den Code, nicht in den Prompt",[14,276,277,279],{},[42,278,251],{}," hat einen eingebauten Agenten, der gegen ein lokales Sprachmodell\narbeitet, llama-server mit Qwen3-4B. Ein Agent im Editor braucht Werkzeuge,\nund Werkzeuge brauchen Grenzen. Der naheliegende Weg ist, die Grenzen in den\nSystemprompt zu schreiben. Bei einem Modell dieser Grösse ist eine\nPrompt-Zeile aber nur eine Bitte, und sie kostet bei jeder Anfrage Platz in\neinem Kontext von 8192 Tokens. Deshalb stehen die Grenzen im Code. Dort\nmüssen sie allerdings lückenlos sein.",[14,281,282,283,286,287,290],{},"Ein Beispiel. Wer eine bestehende Datei überschreiben will, bekommt einen\nBestätigungsdialog. Das Modell hat ihn beim ersten Versuch umgangen: statt\n",[42,284,285],{},"write_file"," schickte es ein ",[42,288,289],{},"replace_text",", dessen Suchtext die ganze Datei\nwar. Formal keine Überschreibung, praktisch genau das.",[14,292,293,294,296],{},"Seither zählt auch ",[42,295,289],{}," als Überschreiben, sobald es die halbe\nDatei oder mehr ersetzt:",[298,299,304],"pre",{"className":300,"code":301,"language":302,"meta":303,"style":303},"language-zig shiki shiki-themes github-light github-dark","\u002F\u002F\u002F replace_text mit `old` = (fast) ganzer Datei ist ein verkapptes Überschreiben und\n\u002F\u002F\u002F braucht dieselbe Bestätigung wie write_file auf eine bestehende Datei.\npub fn replaceCountsAsRewrite(file_len: usize, old_len: usize) bool {\n    if (file_len == 0) return false;\n    return old_len * 2 >= file_len;\n}\n","zig","",[42,305,306,314,320,326,332,338],{"__ignoreMap":303},[307,308,311],"span",{"class":309,"line":310},"line",1,[307,312,313],{},"\u002F\u002F\u002F replace_text mit `old` = (fast) ganzer Datei ist ein verkapptes Überschreiben und\n",[307,315,317],{"class":309,"line":316},2,[307,318,319],{},"\u002F\u002F\u002F braucht dieselbe Bestätigung wie write_file auf eine bestehende Datei.\n",[307,321,323],{"class":309,"line":322},3,[307,324,325],{},"pub fn replaceCountsAsRewrite(file_len: usize, old_len: usize) bool {\n",[307,327,329],{"class":309,"line":328},4,[307,330,331],{},"    if (file_len == 0) return false;\n",[307,333,335],{"class":309,"line":334},5,[307,336,337],{},"    return old_len * 2 >= file_len;\n",[307,339,341],{"class":309,"line":340},6,[307,342,343],{},"}\n",[14,345,346,347,350],{},"Dasselbe gilt für Pfade. Statt dem Modell zu sagen, es solle im Projekt\nbleiben, löst eine Funktion den Pfad auf und gibt nichts zurück, wenn er\nausserhalb liegt. Ein Pfad, der über ",[42,348,349],{},".."," oder absolut aus dem Projekt\nhinausführt, kann dann gar keine Dateioperation erzeugen.",[14,352,353],{},"Solche Regeln sind reine Funktionen, und reine Funktionen kann man testen.\nEine Prompt-Zeile kann man nur hoffen.",[14,355,356,357,360],{},"Umgekehrt gilt dasselbe für Fähigkeiten. Das Werkzeug ",[42,358,359],{},"command"," bekommt\nseine Auswahl aus der Kommando-Aufzählung des Editors erzeugt. Jedes Menü und\njedes Tastenkürzel ist damit automatisch für den Agenten erreichbar, ohne\ndass irgendwo eine zweite Liste gepflegt werden müsste.",[14,362,363],{},"Auch die Frage, in welchem Fenster eine vom Agenten geöffnete Datei\nerscheint, ist keine Anweisung an das Modell, sondern eine Funktion mit\nUnit-Test. Der Systemprompt ist auf drei Sätze geschrumpft: die Rolle, die\nKonvention, dass Pfade relativ zum Projekt gemeint sind, und die Bitte, nach\nWerkzeugergebnissen kurz in der Sprache des Nutzers zu antworten. Alles\nandere steht im Code, wo es geprüft wird, statt im Prompt, wo es erbeten\nwird.",[21,365,367],{"id":366},"was-offen-bleibt","Was offen bleibt",[14,369,370],{},"Es gibt Grenzen, die bewusst stehenbleiben. Der Editor lädt genau einen\nSchriftschnitt, deshalb zeigt die Markdown-Ansicht fett und kursiv über\nFarben statt über echte Schnitte. Solche Punkte stehen als Entscheidung in der\nProjektdokumentation, nicht als offene Aufgabe.",[372,373,374],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":303,"searchDepth":316,"depth":316,"links":376},[377,378,379,380,381,382,383],{"id":23,"depth":316,"text":24},{"id":33,"depth":316,"text":34},{"id":74,"depth":316,"text":75},{"id":84,"depth":316,"text":85},{"id":244,"depth":316,"text":245},{"id":273,"depth":316,"text":274},{"id":366,"depth":316,"text":367},"Von VS Code über Terminal-Editoren und gpui zu Zig. Dreizehn Anläufe mit neun Oberflächen-Bibliotheken, und warum Werkzeuggrenzen für einen KI-Agenten in den Code gehören.","md",{},true,"\u002Fopen-source\u002Feditor-suche",null,{"title":5,"description":384},"open-source\u002Feditor-suche","Cygd2atAi56drF0RhRaTub29HteBFCBAj0ntsEHSU-E",1789248179574]