Meditor

Aus Physik
Zur Navigation springen Zur Suche springen

Ziel

Ein professioneller Editor für Matlab

Features:

  • Syntax-Highlighting
  • Automatische Einrückung
  • Matching Brackets
  • Templates?
  • Hilfefunktionen?
    • Für Matlab - Funktionen wird die passende Matlab-Hilfeseite aufgerufen (Browser)
      • korrekter Seitennamen kann oft aus dem Funktionsnamen generiert werden
      • Ausnahmen könnten in einem assiozativen Array gespeichert werden (ist Funktionsname im Array, dann nimm die darin angegebene Seite, ansonsten generiere einen Seitennamen)


Versionen

(Milestones wär wohl übertrieben ;-)

Version 1.0.1

Was geht

  • Partitionierung als Basis für Syntax-Highlighting und Operationen im Dokument
    Partitionstypen:
           IDocument.DEFAULT_CONTENT_TYPE,
           MATLAB_COMMENT,
           MATLAB_SINGLELINE_STRING,
           MATLAB_MULTILINE_COMMENT,
           MATLAB_KEYWORD, 
           MATLAB_FUNCTION, 
           MATLAB_CODE, 
           MATLAB_NUMBER, 
           MATLAB_WHITESPACE, 
           MATLAB_NEWLINE
  • Syntax-Highlighting verfeinert
    • Arbeitet nur mehr mit Partitionen (generiert von MatlabPartitionScanner)
    • Hervorgehoben werden:
      • Kommentare
      • Strings
      • Keywords
      • Matlab-Funktionen
      • Zahlen
  • Automatische Einrückung
    • Wenn man eine neue Zeile anfängt
      • die beendete Zeile wird passend eingerückt
      • in der neuen Zeile beginnt man mit passender Einrücktiefe
    • Wenn man ein Keyword fertiggetippt hat (und danach ein Whitespace einfügt)
      • die aktuelle Zeile wird passend eingerückt
    • Bei Eingabe eines Tabs am Zeilenanfang oder im Whitespacebereich am Beginn einer Zeile
      • die aktuelle Zeile wird passend eingerückt
      • Cursor springt an das Ende der Einrückung
    • Vom User einstellbare Sachen:
      • ob die Einrückung mit Tabs oder mit Leerzeichen erfolgen soll
      • Einrücktiefe

Was fehlt - Schritte bis zur nächsten Version

  • Partitionierung verbessern:
    • Differenzieren zwischen dem ' Operator und Strings Teilweise gelöst
    • Bei Eingaben wird die vorhergehende Partition nicht aktualisiert, was in einigen Fällen eine falsche Partitionierung nach sich zieht
  • Änderungen der Preferences Page sollen sofort Auswirkungen zeigen Funktioniert
  • Einrückstragegie um Fortsetzungszeilen erweitern Funktioniert
  • Einrücken von ganzen Bereichen Funktioniert

Archiv

Diese Seite bei Fertigstellung der Version 1.0.1


Anfänglich vorhandene Strukturen

In grün Geschriebenes sind die selbst entwickelten Klassen.

Editor

...
  |- org.eclipse.ui.texteditor.AbstractTextEditor
       |- org.eclipse.ui.texteditor.StatusTextEditor
            |- org.eclipse.ui.texteditor.AbstractDecoratedTextEditor
                 |- org.eclipse.ui.editors.text.TextEditor
                      |- at.tugraz.itp.mltutor.meditor.editors.MatlabEditProjection
                           |- at.tugraz.itp.mltutor.meditor.editors.MatlabEditor


Neue Strukturen

Ersetzte deprecated Klassen

  • DefaultPartitioner durch FastPartitioner
    • FastPartitioner implementiert alle benötigten Funktionalitäten, somit keine weiteren Änderungen
  • org.eclipse.ui.help.WorkbenchHelp soll ersetzt werden durch org.eclipse.ui.help.IWorkbenchHelpSystem
    • zumindest laut Eclipse-Hilfe, was aber nicht direkt geht (ist ja auch ein Interface)
    • Ein neues Hilfesystem, welches aber weniger kann als org.eclipse.ui.help.WorkbenchHelp, ist org.eclipse.help.HelpSystem
    • Mit IWorkbenchHelpSystem IWorkbench.getHelpSystem() kann eine Instanz des passenden Interfaces geholt werden.
      • Ein IWorkbench Objekt wiederum bekommt man mit static IWorkbench PlatformUI.getWorkbench()
    • Ein Beispiel:
      Statt WorkbenchHelp.setHelp(...);
      Wird jetzt PlatformUI.getWorkbench().getHelpSystem().setHelp(...) verwendet.
  • Indent Strategy
    • IAutoIndentStrategy ist durch IAutoEditStrategy zu ersetzen
    • damit auch die Funktion getAutoIndentStrategy(...) durch getAutoEditStrategies(...)
    • MatlabAutoIndentStrategy (von DefaultAutoIndentStrategy abgeleitet) wurde ersetzt durch MatlabAutoEditStrategy (von IAutoEditStrategy abgeleitet)

Partitionierung des Dokuments

Partitionstypen

           IDocument.DEFAULT_CONTENT_TYPE,
           MATLAB_COMMENT,
           MATLAB_SINGLELINE_STRING,
           MATLAB_MULTILINE_COMMENT,
           MATLAB_KEYWORD, 
           MATLAB_FUNCTION, 
           MATLAB_CODE, 
           MATLAB_NUMBER, 
           MATLAB_WHITESPACE, 
           MATLAB_NEWLINE, 
           MATLAB_CONTINUATION

Partitionscanner und neue Rules

MatlabScanner wurde entfernt. Die darin enthaltenen Funktionalitäten wurden in MatlabPartitionScanner eingebaut. Da dieser nicht mit WordRule umgehen kann, wurde eine neue innere Klasse für das Detektieren der Keywörter eingeführt:

static class WordPredicateRule extends WordRule implements IPredicateRule{
    public WordPredicateRule(IWordDetector detector, IToken successToken, IToken defaultToken);
    ...
}

Anwendung des Adapter (genauer Klassenadapter) Patterns.

Das selbe Spiel wurde für WhitespacePredicateRule gespielt.
Für letztere wird noch eine neue Klasse WhitespaceDetector gebraucht:

private class WhitespaceDetector implements IWhitespaceDetector {
    WhitespaceDetector(char[] whitespaces){}
    public boolean isWhitespace(char c) {}
}

Um Regular Expressions verwenden zu können gibt es die Klasse RegExRule

public class RegExRule implements IPredicateRule {
    public RegExRule(IToken token, Pattern pattern, Pattern completePattern) {}
    ...
}

Unterscheidung Funktionen - Keywords

Leider ist es etwas schwierig mehrere Rules für verschiedene Wortlisten zu implementieren (es funktioniert auf die naheliegende Weise nicht). Deshalb wurde eine (innere) Hilfsklasse WordListRuleGenerator eingeführt, die eine WordPredicateRule aus mehreren Wortlisten erzeugt. Dabei gehört zu jeder Wortliste ein Token, sodass verschiedene Partitionen für verschiedene Wortlisten erzeugt werden, wobei bisher lediglich zwischen den Matlab-Funktionen und Keywords unterschieden wird. Als Keywords wird der Output der Matlab-Funktion iskeyword verwendet:
'break' 'case' 'catch' 'continue' 'else' 'elseif' 'end' 'for' 'function' 'global' 'if' 'otherwise' 'persistent' 'return' 'switch' 'try' 'while'
(entnommen aus der Matlab Hilfe: http://www.mathworks.com/access/helpdesk/help/techdoc/ref/iskeyword.html)

class WordListRuleGenerator {
    public WordListRuleGenerator();
    public void addWordList(String[] words, IToken token);
    public IPredicateRule generateRule(IWordDetector detector, IToken successToken, IToken defaultToken);
}

Automatische Einrückung

Anforderungen

Funktionalität:

  • Beim Wechsel in eine neue Zeile (Enter)
    • Übernehmen der Einrücktiefe
    • Automatisches Ein- und Ausrücken nach bestimmten Keywords (for, ...)
      • Dies kann die aktuelle Zeile oder eine nach einem Umbruch neu erzeugte betreffen
  • Verhalten der Tab-Taste wie im Emacs (auch Java-Editor von Eclipse)
  • korrekte Einrückung für einen ganzen Abschnitt (das ganze Dokument)

Stragegie

char command enthält das zuletzt eingetippte "Zeichen".

Beim Sprung in eine neue Zeile

  1. vorhergehende Zeile holen, Einrücktiefe feststellen
  2. vorhergehende Zeile analysieren, dabei mit Partitionen arbeiten (damit können Kommentare leicht ignoriert werden)
    • für jedes Keyword für mehr Einrückung (for, if, else, elseif, ...)
      => Einrücken
    • für jedes Keyword für weniger Einrückung (end, ...)
      => Ausrücken
    • bei Fortsetzungszeilen um einen Fixbetrag gegenüber der ersten fortgesetzten Zeile einrücken
  3. tatsächliche Einrückung für die vorhergehende und die neue Zeile herstellen (passende Whitespaces)
  4. falls der Umbruch mitten in einer Zeile erzeugt wurde, so soll der Textcursor an das Ende des Whitespacebereichs am Anfang der neuen Zeile positioniert werden

Nach dem Fertigtippen eines Keywords

  1. Zeile holen
  2. Vorherige Partition holen
  3. Wenn diese ein Keyword war
    1. Einrücktiefe der vorherigen Zeile feststellen
    2. Einrücktiefe der aktuellen Zeile korrigieren

Drücken von Tab

  1. Feststellen, ob dieses am Zeilenanfang oder im Whitespacebereich am Beginn einer Zeile eingegeben wurde
  2. vorhergehende Zeile analysieren
  3. Einrücktiefe der aktuellen Zeile korrigieren
  4. Textcursor an das Ende des Whitespacebereichs setzen

Multilinecomments werden derzeit nicht behandelt!
Das Problem ist, dass jede Zeile, die vollständig in einem Multilinecomment liegt, nur aus einer dazugehörigen Partition besteht. D.h. der führende Whitespacebereich ist keine Whitespace-Partition, was eine gesonderte Behandlung der Einrückung solcher Zeilen erforderlich macht.

Struktur

Neue Singleton Klasse:

public class MatlabAutoEditStrategy implements IAutoEditStrategy {
    public static MatlabAutoEditStrategy getInstance(){}
    public void setupStrategy(){}
    public void customizeDocumentCommand(IDocument document, DocumentCommand command) {}
    ...
}

Diese wird explizit ansonsten möglichst nirgends verwendet!

Jedoch wird sie für Reinitialisierungsarbeiten nach Änderungen in der Preferences Page benötigt werden, was meiner Meinung nach OK ist, da die speziellen Einstellungen und unsere spezielle Klasse zusammengehören. (--Osiris 12:43, 9 December 2005 (CET))

Allgemein weiß MatlabConfiguration was von der Indent Strategy, wobei dort IAutoEditStrategy benutzt wird.

Für das korrekte Einrücken eines markierten Bereichs gibt es die Klasse

MatlabIndentationAction extends MatlabAction implements IEditorActionDelegate {
    public MatlabIndentationAction(String text) {}
    public MatlabIndentationAction() {}
    public void run(IAction action) {}
    public void setActiveEditor(IAction action, IEditorPart targetEditor) {}
}

welche haupstächlich das Verhalten von MatlabAction übernimmt.

Leider ist mir noch kein Weg untergekommen um aus der Klasse heraus (über MatlabConfiguration) an die vom Framework verwendete Instanz von MatlabAutoEditStrategy heranzukommen, weshalb ich mich dazu entschloss letztere als Singleton auszuführen. Ich wählte die einfachste Thread-save Implementierung die mir bekannt ist. --Osiris 14:48, 4 January 2006 (CET)

Die Action ist nur über die plugin.xml hinzugefügt und über den Menüpunkt Edit -> Correct Indentation erreichbar.

Änderungen der Textfarben in der PropertyPage sofort übernehmen

Grundstruktur

In MatlabEditor.init(...) wird ein Preferences.IPropertyChangeListener() angelegt, welcher bei Änderung einer Textfarbe MatlabConfiguration.updateSyntaxColor(...) aufruft.
In der letztgenannten Funktion wird der passende NonRuleBasedDamagerRepairer geholt und dessen TextAttribute durch ein neues ersetzt.

Hinzugefügte Strukturen

  • NonRuleBasedDamagerRepairer.setTextAttribute(TextAttribute textAttribute)
  • MatlabConfiguration.updateSyntaxColor(String name)
    die DamagerRepairer aller zu der angegebenen Farbe gehörenden Partitionstypen werden aktualisiert.

Im Zuge dessen wurde das Initialisieren des PresentationReconciler (Funktion MatlabConfiguration.getPresentationReconciler(...) refactored.


Weitere Schritte

Partitionierung

Weiters ist das Problem des ' Zeichens zu lösen. Wird dieses als Operator zwei Mal in einer Zeile verwendet, so wird der dazwischenliegende Teil als String interpretiert.

  • Idee: Es gibt eine Regular Expression für Strings mit 'bla', mit der eine RegExRule statt der SinglelineRule verwendet wird. Diese regex müsste dahingehend erweitert werden, dass nur "gültige" Strings als solche erkannt werden
    • Lösung dafür: Lookback. Allerdings kann damit nur auf Ausdrücke bekannter Länge geprüft werden (also nicht ob z.B. ein beliebiger Variablenname vor dem ' Zeichen steht). Man könnte aber sagen, dass das letzte Zeichen vor dem Kommentar kein Buchstabe, keine Zahl und keine schließende Klammer sein darf.
      • Problem: Lookback ist von Java-Regex unterstützt, funktioniert aber nicht
        • An java.util.regex.Pattern liegt's eher nicht, da eine andere Library (JRegex) sich gleich verhält
        • Die RegExRule funktioniert prinzipiell, da Ausdrücke ohne Lookback erkannt werden.
        • Ich glaube eher, dass das prinzipielle Vorgehen bei der Partitionierung nicht geeignet für Lookbacks ist (zumindest ohne grobe Umbauten). --Osiris 15:10, 3 January 2006 (CET)
    • Workaround: vor dem öffnenden ' muss ein (Regex-)Whitespace stehen. Damit werden zwar nicht alle gültigen Strings erkannt, aber dafür sicher kein "ungültiger"

Automatische Einrückung

Verfeinerung: "schließende" Keywords suchen sich ihre "öffnenden" Partner.

  • Damit wird z.B. der Fehler, dass das Konstrukt for bla end ausgerückt wird, unterbunden.
    • Generell können damit vom User verrücktere Konstrukte eingegeben und passend eingerückt werden.
  • Einrückverhalten könnte vom User frei konfigurierbar gemacht werden
  • switch - case - end wird schöner machbar

Vervollständigung: Auch Text in Multilinecomments wird passend behandelt

Hilfesystem

Anforderung

Es soll möglich sein, für eine ausgewählte Funktion (z.B. Textcursor im Funktionsnamen) die Matlab-Hilfe aufzurufen.

Umsetzung

  • Öffnen eines Browserfensters, Name der Funktion ist Teil der URL
    • Problem: Nicht immer passt der Name (z.B. Operatoren und die zu ihnen äquivalenten Funktionen müssen auf die selbe Hilfeseite verweisen)
      • Lösungsidee: Ausnahmen werden in einer Map gespeichert (Key: Funktionsname, Value: passender Text für die Hilfeseite)


Diverses

Archiv

Hier werden für die aktuelle Entwicklung nicht mehr relevante Texte archiviert.

Anmerkungen zur Entwicklung

Folgende Plugins werden vom Meditor-Plugin benötigt (einzutragen bei Dependencies)

  • org.eclipse.ui
  • org.eclipse.core.runtime
  • org.eclipse.ui.workbench.texteditor
  • org.eclipse.jface.text
  • org.eclipse.ui.editors
  • org.eclipse.core.resources
  • org.eclipse.ui.ide
  • org.eclipse.ui.views
  • org.eclipse.jdt.ui
  • org.eclipse.help

Patterns
Einer der Vorteile von Patterns ist die sehr gute Kommunizierbarkeit. Damit dieser jedoch überhaupt zum Tragen kommen kann müssen verwendete Patterns auch genannt werden. Deshalb werden im Zuge des Ausbaus des Editors neue Anwendungen von Patterns entsprechend gekennzeichnet.

Erstellen eines eigenen Editors (nur Anmerkungen)

  1. Klasse von AbstractTextEditor ableiten
  2. Klasse von SourceViewerConfiguration ableiten
    Dies ist der Ausgangspunkt für das Hinzufügen von eigenen Funktionalitäten
  3. Einen DocumentProvider erweitern um ein IDocument Objekt, welches die Datenrepräsentation darstellt, zu erhalten. Dies ist auch der Ausgangspunkt für Notifacations.
  4. Actions werden in der Funktion createActions() (Memberfunktion des erzeugten Editors) hinzugefügt.


Fragen

Offene

  • Soll das Syntax-Highlighting noch verfeinert werden? Derzeit wird folgendes hervorgehoben:
    Kommentare, Zahlen, Strings, Matlab-Funktionen, Keywords
    • Operatoren wären noch möglich (schnell über regex implementierbar)
  • Weiß wer wie man an die verwendete SourceviewerConfiguration rankommt?

Erledigte