Meditor

Aus Physik
Zur Navigation springen Zur Suche springen

Ziel

Ein professioneller Editor für Matlab

Features:

  • Syntax-Highlighting Funktioniert
  • Automatische Einrückung Funktioniert, darf noch verbessert werden
  • Matching Brackets Funktioniert
  • Templates?
  • Hilfefunktionen?
    • Für Matlab - Funktionen wird die passende Matlab-Hilfeseite aufgerufen (Browser)


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 Funktioniert
  • Änderungen der Preferences Page sollen sofort Auswirkungen zeigen Funktioniert
  • Einrückstragegie um Fortsetzungszeilen erweitern Funktioniert
  • Einrücken von ganzen Bereichen
    Erreichbar über
    • Menü Funktioniert
    • Kontextmenü
    • Key Binding

Archiv

Diese Seite bei Fertigstellung der Version 1.0.1

Version 1.0.2 (in Arbeit)

Was geht (zusätzlich zur Version 1.0.1)

  • Partitionierung
    • neue Partition MATLAB_CONTINUATION
    • unsinige Partition MATLAB_MULTILINE_COMMENT entfernt
    • Unterscheidung zwischen Strings und dem ' Zeichen als Operator funktioniert
  • Automatische Einrückung
    • Fortsetzungszeilen werden behandelt
    • Einrücken von ausgewählten Bereichen (über Menüpunkt)
  • Preferences
    • Änderungen zeigen sofort Wirkung
  • einige Refactorings im Code
  • Syntax-Highlighting
    • Fortsetzungsoperator (...) wird mit allem was nach ihm in einer Zeile steht als Kommentar hervorgehoben
  • Textoperationen
    • Beim Löschen/Einfügen von Passagen (auch von mehreren Zeilen) werden Partitionierung, Einrückung und Darstellung aktualisiert

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

Viewer

...
  |- org.eclipse.jface.text.source.projection.ProjectionViewer
       |- at.tugraz.itp.mltutor.meditor.editors.MatlabSourceViewer

Problem: von ProjectionViewer soll eigentlich nicht abgeleitet werden.


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_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) {}
    public RegExRule(IToken token, Pattern pattern, Pattern completePattern, Pattern lookbackPattern, int lookbackLen) {}
    ...
}

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
  • laufende Aktualisierung der Einrücktiefe (wenn z.B. ein Teil eines Keywords gelöscht wird)
    • korrekte Einrückung für mit copy and paste eingefügte Bereiche
  • 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.

Löschen und Einfügen von Textteilen

  1. Feststellen welche Zeilen betroffen sind
  2. Diese passend einrücken

Struktur

Neue Singleton Klasse:

public class MatlabAutoEditStrategy implements IAutoEditStrategy {
    public static MatlabAutoEditStrategy getInstance(){}
    public void setSourceViewer(ISourceViewer sourceViewer){
    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))

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.

Querverbindungen:

  • Folgende Klassen wissen was von der konkreten Indent Strategy
    • MatlabConfiguration
      nur innerhalb der Funktion getAutoEditStrategies(...)
    • MatlabEditor
      nur für die Initialisierung des IPropertyChangeListener (um auf Änderungen in der PropertyPage reagieren zu können)
    • MatlabIndentationAction
  • Damit die Indent Strategy die Aktualisierung der Ausgabe erzwingen kann, muss ihr der Source Viewer bekannt gegeben werden, was in der Funktion MatlabConfiguration.getAutoEditStrategies(ISourceViewer sourceViewer, ...) leicht erledigt werden kann.
Offensichtlich ist es auch so gedacht, dass die Indent Strategie "ihren" Source Viewer kennt - klingt ja auch plausibel. --Osiris 15:37, 5 January 2006 (CET)

Änderungen in der PropertyPage sofort übernehmen

Grundstruktur

In MatlabEditor.init(...) wird ein Preferences.IPropertyChangeListener() angelegt, welcher bei Änderung einer Textfarbe MatlabConfiguration.updateSyntaxColor(...) und bei Änderungen an den Einstellungen für die Einrückung MatlabAutoEditStrategy.setupStrategy() aufruft.
In der ersten Funktion wird der passende NonRuleBasedDamagerRepairer geholt und dessen TextAttribute durch ein neues ersetzt.

Hinzugefügte Strukturen

  • NonRuleBasedDamagerRepairer.setTextAttribute(TextAttribute textAttribute)
    ist lediglich ein Setter für die bereits vorhanden gewesene Membervariable.
  • 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

  • Automatisierte Erstellung der Wortlisten für die Funktionen
    • Idee: Eigenes Tool das die Matlab-Verzeichnisstruktur durchsucht und die gefundenen Funktionen in einem File speichert.
      Dieses File ist die Basis der Wortliste, die beim Eclipse-Start erstellt wird.
      • Ausgangsverzeichnis: afs/itp.tugraz.at/opt/matlab/R14.sp3/toolbox/matlab/ für die Matlab-Funktionen
      • Es existiert in den Unterverzeichnisen oft ein File Content.m
        • Gibt es weitere Files ohne Funktionsinhalt?
        • Können alle Files, die mit Großbuchstaben beginnen ignoriert werden?

Automatische Einrückung

Erweiterung

  • Wenn man am Ende des Whitespacebereichs am Zeilenanfang einer korrekt eingerückten Zeile ein tab drückt, wird eingerückt.

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: Einrücken von ganzen Bereichen auch vom Kontextmeü aus und über ein Key Binding zugänglich machen
Schön wär's, wenn der Menüpunkt "Indent whole document" heißen würde, wenn nichts markiert ist (ansonsten "Correct Indentation"), und auch genau das gemacht werden würde.

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)

Anstehende Refactorings / Verbesserungen

  • MatlabSourceViewer
    • ist von ProjectionViewer abgeleitet, von der aber nicht abgeleitet werden soll
    • macht außer Unnötigem fast nichts mehr als ProjectionViewer
      • die Ausnahme: in der Funktion canDoOperation(...) wird MatlabEditor.CORRECTIONASSIST_PROPOSALS behandelt, was aber sonst nirgends verwendet wird.
  • MatlabEditor
    • Folgende Felder werden nie verwendet:
      • TEMPLATE_PROPOSALS_ID
      • CONTENTASSIST_PROPOSALS_ID
      • CORRECTIONASSIST_PROPOSALS_ID


Diverses

Weitere Seiten

  • Archiv: Hier werden für die aktuelle Entwicklung nicht mehr relevante Texte archiviert.
  • Benutzerseite: Fehlerberichte und Verbesserungsvorschläge

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 in einer Action an die verwendete SourceviewerConfiguration rankommt?
  • Die im Punkt "Anstehende Refactorings / Verbesserungen" geschilderten Probleme betreffend:
    • Wozu waren die diversen Felder und werden sie evtl. noch irgendwann verwendet?
    • Einwände gegen das Entfernen dieser?
  • Nachdem jetzt auf Java 5 umgestellt wurde, auch ÜBERALL generic types verwenden?

Erledigte