Wie würdet ihr einen Texteditor programmieren



  • Ich möchte einen kleinen Texteditor für die Konsole programmieren. Wie würdet ihr da vorgehen. Irgendwelche besonderen Algorithmen oder Datenstrukturen die man nutzen könnte?



  • Textor schrieb:

    Ich möchte einen kleinen Texteditor für die Konsole programmieren. Wie würdet ihr da vorgehen. Irgendwelche besonderen Algorithmen oder Datenstrukturen die man nutzen könnte?

    Welche Sprache?
    In C++ wäre das sehr schwierig zu bewerkstelligen, weil man auf systemspezifische Funktionen zugreifen muss um die Cursorposition abzufragen, vom Benutzer setzen zu lassen und das Ganze bei Änderungen neu zu zeichnen.
    Deswegen greift man da zu einer GUI-Bibliothek.



  • Textor schrieb:

    Wie würdet ihr da vorgehen.

    gar nicht. es gibt eh schon zu viele.
    zeitverschwendung pur. 👎



  • Nathan schrieb:

    Textor schrieb:

    Ich möchte einen kleinen Texteditor für die Konsole programmieren. Wie würdet ihr da vorgehen. Irgendwelche besonderen Algorithmen oder Datenstrukturen die man nutzen könnte?

    Welche Sprache?
    In C++ wäre das sehr schwierig zu bewerkstelligen, weil man auf systemspezifische Funktionen zugreifen muss um die Cursorposition abzufragen, vom Benutzer setzen zu lassen und das Ganze bei Änderungen neu zu zeichnen.
    Deswegen greift man da zu einer GUI-Bibliothek.

    Im Textmode gibt es dafür "Curses". Wer das nicht mag, muss sowas hässliches wie VI nachbauen.



  • Danke für die Tipps. Nein, ein Vi oder emacs will ich sicher nicht noch einmal der Welt antun. Das war ja mal lustig als man jeden Tastendruck sparen musste, wegen der geringen Übertragungsleistung. Heute ist ein Editor der nicht per default Cut/Copy/Paste und Auswahl per Shift Taste anbietet, schlicht nicht akzeptabel.

    Nano ist dahingehend auch Schrott. Ich habe bis jetzt noch nicht einen "normalen" kleine Texteditor für die Konsole gefunden.



  • Stimmt. Alle Konventionen außer denen von Windows sind kacke.
    Heil Gates.



  • Textor schrieb:

    Heute ist ein Editor der nicht per default Cut/Copy/Paste und Auswahl per Shift Taste anbietet, schlicht nicht akzeptabel.

    Emacs kann Shift per default. Für Strg-X/C/V einfach CUA-Mode aktivieren (M-x cua-mode). Davon abgesehen finde ich die "nativen" Bindings viel angenehmer als die von dir beschriebenen.

    Aber genug getrollt:

    Irgendwelche besonderen Algorithmen oder Datenstrukturen die man nutzen könnte?

    Die Datei als std::string zu halten ist viel zu langsam, da du nicht effizient einfügen/deleten kannst. Vermutlich ist list<string> die beste triviale Lösung.
    Jede Zeilen als String, da diese relativ klein bleiben ist das insert schnell. Textdatei als Liste von Zeilen, da immer nur ein kleiner Bereich an Zeilen gerendert werden muss. Was im Bildschirm sichtbar ist kann noch gecached werden.

    Leicht besser ist der Ansatz von Emacs, wo der Text wie eine std::deque gespeichert wird, aber nach allen 32 Zeichen kommen 32 Füllbytes (Zahlen aus der Luft gegriffen). Fügst du ein Zeichen ein, wird der Text dahinter verschoben, aber nur bis zum nächsten leeren Füllbyte (z.B. das 0-Byte), das dann verwendet wird. Wenn die Struktur entartet werden wieder neue Füllbytes eingefügt. Löschen ist einfach ein das Zeichen in ein Füllbyte verwandeln. (Gap buffer)

    Ein algorithmisch überlegener Ansatz wäre eine Rope, aber der ist recht komplex und hat im "alltäglichen Editorgebrauch" etwas mehr Overhead.

    Mit den Links, die ich dir gegeben habe, dürftest du leicht weitere Alternativen finden.

    Um etwas für die Konsole zu schreiben empfiehlt sich NCurses (!= curses). Ist relativ einfach, im Prinzip kannst du dir deinen 80x24-Zeichen-Buffer (ev. mit Farbannotationen) vollschreiben und mit NCurses auf den Screen dumpen.

    Btw: Ist es in diesem Forum normal, dass alle Antworten Trollantworten sind?



  • Hey danke, das sind sehr wertvolle Anregungen. Jetzt habe ich schon mal eine Richtung in der ich Recherchieren und ausprobieren kann.

    P.S.: Nicht falsch verstehen ich bin reiner Linuxnutzer, finde CutCopyPaste mit den Standardtasten deswegen gut, weil es ein Standard ist und man sich nicht umgewöhnen muss. Es ist besser einen Standard zu haben, als eine Insellösung die ergonomisch besser wäre. Kann ja jeder sehen wie er will.



  • Textor schrieb:

    Ich möchte einen kleinen Texteditor für die Konsole programmieren. Wie würdet ihr da vorgehen. Irgendwelche besonderen Algorithmen oder Datenstrukturen die man nutzen könnte?

    Boyer-Moore zum Suchen ^^

    Die Frage ist, was Du unter klein verstehst.
    Ich habe mal einen eigenen Editor geschrieben und auch einige Jahre genutzt - auch zum Programmieren, weil kein Editor so schön Texte falten konnte, wie meiner. Bis heute. 🙂

    "Besondere" Algorithmen oder Datenstrukturen waren da jetzt nicht drin.

    Für die Konsole würde ich mir auch mal NCurses (Linux) ansehen, damit kann man schon was anfangen. Es gibt auch einen Trick, um an die ESCAPE-Taste zu kommen - daran bin ich damals nämlich gescheitert, weswegen ich meinen Editor nie portiert habe. Ich angefangen, kam da nicht weiter und so drängten sich andere Projekte vor. ^^

    Aus eigener Erfahrung rate ich Dir, Dir vorher Gedanken darüber zu machen, wie Du etwas darstellen möchtest. Mein Editor ist vorrangig daran gestorben, dass er nicht sonderlich flexibel war, die Darstellung auszutauschen, ich habe das Rendern nicht von der eigentlichen Editor-Funktionalität gut genug getrennt.

    Auf dem 3. Bild sieht man, dass man die Ansicht splitten kann. Das habe ich nachträglich eingebaut. Rund 5000 Änderungen zwischen zwei lauffähigen Kompilaten. Sowas kann man sich auch vorher überlegen... ^^

    Ein Editor ist eine hervorragende Programmier-Übung - also alles andere als überflüssig. Und es besteht ja durchaus die Chance, dass der Editor auch was taugt und nach einiger Weiterentwicklung für viele Fälle eine hilfreiches Tool ist.

    Zwei Tipps von meiner Seite noch, die ich bei meinem noch gerne umgesetzt hätte: Schau Dir das Processor-Pattern an, damit Du Undo unterstützen kannst. Ansonsten verwende eigene Datenstrukturen, oder vector< char > statt std::string.
    In meinem Fall gab es eigene Datenstrukturen, eine class Text hatte eine Liste von class TextLine. Betrachte eine TextLine nicht zu statisch. Ich würde heute einen MemoryManager bauen, der Speicher alloziiert und eine Textline, die Bereiche aus diesem Speicher darstellt und zwar in Abhängigkeit zur vorherigen Zeile. So lassen sich Daten unterschiedlich anzeigen und editieren: Man könnte so zwischen Text- und Binärdarstellung hin und her switchen und den Editor nicht nur für Text benutzen, sondern eben als Hex-Editor.

    memacs schrieb:

    Btw: Ist es in diesem Forum normal, dass alle Antworten Trollantworten sind?

    Nicht alle Antworten sind Trolle. Denke Dir den Rest. 🙂



  • Du brauchst auf alle Fälle eine dynamische Speicherreservierung, damit dein Editor keine Beschränkungen unterliegt, wie es mal bei Notepad früher der Fall war.



  • Auch euch möchte ich meinen Dank aussprechen, das sind wirklich sehr hilfreiche und ausführliche Anregungen. An Ncurses habe ich auch schon gedacht und das Command Pattern hatte ich schon mal im Einsatz für ein schönes Undo. Ich denke auch, dass ein Editor alles andere als trivial ist und werde versuche so viel wie es geht vorher zu spezifizieren. Da ich kaum Erfahrung in OOP habe, werde ich da sicherlich viele Fehler machen.

    Aber nur durch Fehler machen lernt man richtig. Hier ist auch mehr der Weg das Ziel. Ich kann bei dem Projekt nur gewinnen.

    Gedanken mache ich mir im Moment am meisten um die Speicherverwaltung. Also was mache ich, wenn die Textgröße den verfügbaren Speicher übersteigt etc.



  • Textor schrieb:

    Gedanken mache ich mir im Moment am meisten um die Speicherverwaltung. Also was mache ich, wenn die Textgröße den verfügbaren Speicher übersteigt etc.

    Entweder darauf hoffen, dass der Computer ausreichend Platz zum swappen hat oder einen Modus, der sich die Zeilenanfänge in der Datei in einem Array merkt und die gemachten Änderungen. Beim Bildschirmaufbau muss sich der Renderer die Daten aus der Datei laden. So brauchst Du verhältnismäßig wenig Speicher, das ganze ist aber eher aufwendig und bei heutigen RAM-Größen nicht mehr wirklich erforderlich.
    Wann bearbeitest Du Texte, die größer als 4GB sind? ^^



  • Naja, auch wenn man 4GB + Swap hat, kann der Speicher schon von anderen Programme belegt sein. Es geht da weniger darum, eine Datei zu bearbeiten dessen Größe den virtuellen RAM des Systems übersteigt.

    Ferner kann es ja sein, dass ich Kernteile aus dem Editor auch mal für Embedded System gebrauchen kann, wo Speicher ein kostbares Gut ist, oder wo ich auch nicht den gesamten Speicher zur Verfügung habe.

    Ich lote halt im Vorfeld schon mal ein paar Probleme aus, die mir so einfallen.



  • Xin schrieb:

    Beim Bildschirmaufbau muss sich der Renderer die Daten aus der Datei laden.

    Es macht Sinn ein paar Bildschirmseiten vor und ein paar Bildschirmseiten hinter der aktiven Bildschirmseite schon geladen zu haben, denn gerade im unmittelbar nahen Bereich wird auch noch am meisten hin und hergescrollt.
    Ich würde daher Blockweise laden und 3 Blöcke bilden, wobei jeder Block so groß ist, dass man bei normaler durchscrollgeschwindigkeit die anderen beiden Blöcke davor oder dahinter schnell im Hintergrund nachladen kann.
    So kommt es zu keinen sichtbaren Verzögerungen.

    BSP:
    Blöcke A, B, C

    B ist der aktive Block
    Wenn der Nutzer nun runterscrollt, kann man per Sprung zu C springen und während man dies tut, wird A verworfen und durch den Inhalt hinter C ausgetauscht.
    Dann wäre die nächste Reihenfolge:
    B, C, A2

    Scrollt man nun zurück, dann springt man von C nach B und A2 wird verworfen und durch A3 mit dem Inhalt vor B ersetzt, also:
    A3, B, C
    wobei B dann wieder der aktive Block ist.

    Dadurch ist es egal, wie groß die Datei auf dem Datenträger ist, sie wird immer ins Ram passen.

    Lediglich bei "Suchen und ersetzen" Modi muss man aufpassen, dass man Änderungen Blockweise in die Datei schreibt, denn sonst könnte es sein, das der Arbeitsspeicher nicht ausreicht, wenn Änderungen nur im RAM gemerkt werden und am Ende, nach dem alle Suchbegriffe gefunden wurden, auf den Datenträger geschrieben werden sollen. In solchen Fällen kann das RAM bei den richtigen Dateien sehr knapp werden.
    Ich hatte so ein Szenario schon auf einem Rechner mit 8 GB RAM.



  • Für grosse Dateien lesen empfiehlt sich mmap, dann kümmert sich das Betriebssystem darum, wann was eingelesen wird.

    Aber wenn am Anfang der Datei ein "a" eingefügt wird, hast du immer das Problem, dass sich jedes Zeichen der Datei geändert hat.

    Bei der Idee von Wichtigstes gibt es ein Problem, wenn ich mit Shift (lol) einen Bereich markiere, der über mehrere Blöcke hinausgeht. Auch sehe ich nicht, was passiert, wenn ich eine neue Datei anfange und 10000 mal "a" eintippe. Gibt es dann einen Riesenblock?

    Das Laden kann aber ev. beschleunigt werden, wenn du dir einen vector<block> erstellst, wobei ein Block entweder ein Rope/Gapbuffer ist oder ein Pointer auf den entsprechenden Inhalt (Grösse z.B. je 128MB) von mmap. Wird ein Block geändert, wandelst du ihn in einen Rope um und wenn zwei Ropes nacheinander liegen, fügst du diese zusammen und löschst einen Eintrag in dem vector.

    So sind die aktiven Bereiche effizient bearbeitbar und der Rest liegt im Speicher bereit (er muss noch nicht einmal von der Platte gelesen worden sein).



  • Möchtest du in erster Linie eine neue GUI drumrumbauen und möglichst schnell vorankommen oder interessieren dich die Tiefen der Editor-Komponente?

    In ersterem Fall kannst du nämlich bestehende Editor-Komponenten nutzen, bspw. http://www.scintilla.org/ und nur deinen Editor drumrum basteln (bspw. macht Notepad++ das so)

    (in zweiterem Fall kannst du ja mal etwas in den Source von Scintilla schauen)

    MfG SideWinder



  • Danke für die zusätzlichen Gedanken. Ich möchte schon alles selbst machen. Es ist auch eher der Weg das Ziel. Der Editor soll auch nur in der Konsole funktionieren, obwohl ich den Kern gern auch so schreiben will, dass er mit Anpassungen auch in einem mehrzeiligen Textfeld einer GUI funktionieren könnte.

    Eine Klasse für eine Robe Datenstruktur könnte mir aber schon helfen. Wäre toll wenn es freie Software wäre, also nicht GPL denn die ist ja nicht frei, sondern stellt Bedingungen.



  • Ich habe mir mal den SGI STLPort runter geladen und kompiliert. Ich hoffe mal das ist der beste Weg an eine gute Rope-Implementierung zu kommen.


Anmelden zum Antworten