So erstellen Sie eine Xcode Source Editor-Erweiterung

Was Sie erstellen werden

Einführung

Xcode ist die Haupt-IDE (Integrated Development Environment), die täglich von Tausenden von Entwicklern verwendet wird. Es ist ein großartiges Werkzeug, aber manchmal möchten Sie einige seiner Funktionen und Verhaltensweisen an Ihren Workflow anpassen.

Bis Xcode 7 war es möglich, Code zur Laufzeit in Xcode einzufügen, um Plugins zu erstellen. Plugins können über eine großartige App namens Alcatraz eingereicht und verteilt werden. Dies ist in Xcode 8 nicht mehr möglich.

Xcode 8 überprüft jede Bibliothek und jedes Bundle, um zu verhindern, dass schädlicher Code ohne Ihre Erlaubnis ausgeführt wird. Beim Start von Xcode werden zuvor installierte Plugins mit Alcatraz nicht mehr geladen. Allerdings ist nicht alles verloren, auch Apple kündigte auf der WWDC die Möglichkeit an, sich weiterzuentwickeln Xcode Source Editor-Erweiterungen Damit kann jeder vorhandene Quellbearbeitungsfunktionen erweitern. Lassen Sie uns einen Blick darauf werfen, was wir mit solchen Erweiterungen erreichen können.

1. Erste Schritte

Xcode 8 Source Editor-Erweiterungen sind ein erster Schritt in die richtige Richtung. Wenn Sie seit einiger Zeit mit Xcode arbeiten, befinden Sie sich möglicherweise in einer Situation, in der Sie sich wünschten, dass eine bestimmte Aufgabe innerhalb von Xcode automatisiert werden könnte. Mit Quell-Editor-Erweiterungen können Drittanbieteranwendungen eine Quelldatei ändern. Dies ist genau das, was Sie zur Beschleunigung Ihres Workflows benötigen.

In diesem Moment können Erweiterungen nur mit dem Quellcode interagieren. Dies bedeutet, dass nicht jedes über Alcatraz verfügbare Plugin durch eine Quelltexteditorerweiterung ersetzt werden kann. Aber wer weiß, was die Zukunft bringt.

Es ist wichtig zu verstehen, dass jede Erweiterung in einer macOS-App enthalten sein muss. Sie können beispielsweise Voreinstellungen und Erklärungen zu den Funktionen der Erweiterung in der macOS-App hinzufügen und über den Mac App Store verteilen. Beachten Sie auch, dass jede Erweiterung in a läuft separater Prozess. Wenn die Erweiterung abstürzt, stürzt Xcode nicht ab. Stattdessen wird eine Meldung angezeigt, dass die Erweiterung ihre Arbeit nicht beenden konnte.

Außerdem Erweiterungen habe keine Benutzeroberfläche Sie können den Code nur direkt ändern, wenn der Benutzer Ihren Befehl aufruft. Sie können beispielsweise nicht im Hintergrund laufen.

Ich empfehle die WWDC 2016-Sitzung über Quelltexteditor-Erweiterungen. Es erklärt nicht nur, wie Sie mit der Entwicklung von Xcode Source Editor-Erweiterungen beginnen, sondern enthält auch Tipps und Verknüpfungen, um Ihre Entwicklung zu beschleunigen.

2. Übersicht

In diesem Tutorial werden wir eine Erweiterung entwickeln, die die Schließsyntax in Swift bereinigt. Xcode führt automatisch eine Schließsyntax mit den Klammern aus, sie können jedoch der Kürze halber weggelassen werden. Dies ist eine Aufgabe, die leicht automatisiert werden kann, indem sie in eine Quelltexteditor-Erweiterung eingebunden wird.

Die kürzere Erklärung für das, was wir entwickeln werden, ist eine Erweiterung, die jede Schließung in eine einfachere und sauberere Syntax umwandelt. Schauen Sie sich das Beispiel unten an.

// vor session.dataTask (mit: url) (Daten, Antwort, Fehler) in // nach session.dataTask (mit: url) Daten, Antwort, Fehler in

3. Projekteinrichtung

Es ist selbstverständlich, dass für dieses Tutorial Xcode 8 erforderlich ist. Sie können es von der Entwickler-Website von Apple herunterladen. Es läuft sowohl unter OS X 10.11 als auch unter macOS 10.12.

Erstelle eine neue OS X Projekt des Typs Kakaoanwendung und gib ihm den Namen CleanClosureSyntax. Stellen Sie sicher, dass Sie die Sprache des Projekts auf festgelegt haben Schnell. Wir werden das Neue nutzen Swift 3 Syntax in diesem Tutorial.

Wir werden die macOS-App vorerst leer lassen und uns auf die Erstellung der Xcode Source Editor-Erweiterung konzentrieren. Von dem Datei Menü wählen Neu> Ziel… . Wählen Sie in der linken Seitenleiste OS X und wählen Sie Xcode Source Editor Erweiterung von der Liste.

Klicken Nächster und setzen Produktname zu Reiniger. Ein neues Ziel wird für Sie erstellt. Klicken aktivieren Sie wenn Sie von Xcode gefragt wird, ob das neu erstellt wurde Planen sollte aktiviert sein.

4. Projektstruktur

Lassen Sie uns zunächst analysieren, was Xcode gerade für uns erstellt hat. Erweitere die Reiniger Ordner, um den Inhalt anzuzeigen.

Wir werden nicht ändern SourceEditorExtension.swift In diesem Lernprogramm kann die Erweiterung jedoch noch weiter angepasst werden. Das extensionDidFinishLaunching () Die Methode wird aufgerufen, sobald die Erweiterung gestartet wird, sodass Sie bei Bedarf eine Initialisierung durchführen können. Das commandDefinitions property getter kann verwendet werden, wenn Sie bestimmte Befehle dynamisch anzeigen oder ausblenden möchten.

SourceEditorCommand.swift ist das hören der Erweiterung. In dieser Datei werden Sie die Logik für die Erweiterung implementieren. Das durchführen (mit: completionHandler :) Diese Methode wird aufgerufen, wenn der Benutzer Ihre Erweiterung startet. Das XCSourceEditorCommandInvocation Objekt enthält eine Puffer Diese Eigenschaft wird verwendet, um auf den Quellcode in der aktuell ausgewählten Datei zuzugreifen. Der Completion-Handler sollte mit Wert aufgerufen werden Null wenn alles gut gelaufen ist, ansonsten übergeben sie eine NSError Beispiel.

5. Implementierung der Erweiterung

Jetzt, da das Projekt alle erforderlichen Ziele enthält, können wir mit dem Schreiben der Erweiterung beginnen. Um es zusammenzufassen, möchten wir die Klammern von Schließungen in einer Swift-Datei entfernen. Dies kann in drei Schritten erfolgen:

  • finde die Zeilen, die einen Abschluss enthalten
  • Entfernen Sie die beiden Klammern aus dieser bestimmten Zeile
  • ersetzen Sie die modifizierte Zeile

Lass uns anfangen.

Wir können einen Regex (regulären Ausdruck) verwenden, um jede Codezeile zu analysieren und zu sehen, ob sie einen Abschluss enthält. Sie können sich auf Akiels Tutorial zu Swift und regulären Ausdrücken beziehen, wenn Sie mehr über reguläre Ausdrücke erfahren möchten. Sie können RegExr verwenden, um Ihre regulären Ausdrücke zu testen. Schauen Sie sich den folgenden Screenshot an, um zu sehen, wie ich meinen Regex getestet habe.

Öffnen SourceEditorCommand.swift und ändern Sie die durchführen (mit: completionHandler :) Methode, um so auszusehen:

func perform (mit Aufruf: XCSourceEditorCommandInvocation, completionHandler: (NSError?) -> Void) -> Void var updatedLineIndexes = [Int] () // 1. Zeilen finden, die eine schließende Syntax für lineIndex in 0 enthalten < invocation.buffer.lines.count  let line = invocation.buffer.lines[lineIndex] as! NSString do  let regex = try RegularExpression(pattern: "\\.*\\(.+\\).+in", options: .caseInsensitive) let range = NSRange(0… < line.length) let results = regex.matches(in: line as String, options: .reportProgress, range: range) // 2. When a closure is found, clean up its syntax _ = results.map  result in let cleanLine = line.remove(characters: ["(", ")"], in: result.range) updatedLineIndexes.append(lineIndex) invocation.buffer.lines[lineIndex] = cleanLine   catch  completionHandler(error as NSError)   // 3. If at least a line was changed, create an array of changes and pass it to the buffer selections if !updatedLineIndexes.isEmpty  let updatedSelections: [XCSourceTextRange] = updatedLineIndexes.map  lineIndex in let lineSelection = XCSourceTextRange() lineSelection.start = XCSourceTextPosition(line: lineIndex, column: 0) lineSelection.end = XCSourceTextPosition(line: lineIndex, column: 0) return lineSelection  invocation.buffer.selections.setArray(updatedSelections)  completionHandler(nil) 

Zeilen mit Schließsyntax suchen

Wir erstellen zuerst ein Array von Int Werte, die die Zeilenindizes der modifizierten Zeilen enthalten. Das liegt daran, dass wir nicht alle Zeilen ersetzen wollen. Wir möchten nur die Zeilen ersetzen, die wir ändern.

Wir listen über alle Zeilen der invocation.puffer Objekt und wir versuchen, eine Übereinstimmung für die zu finden Regulären Ausdruck Objekt. Wenn ich die Escape-Zeichen aus der Regex entferne, sieht das folgendermaßen aus:

. * (. +). + in

Dieser reguläre Ausdruck stimmt überein, wenn eine Zeichenfolge die folgenden Merkmale aufweist:

  • Es hat eine geschweifte Klammer (), gefolgt von 0 oder mehr Zeichen, mit Ausnahme eines neuen Zeilenzeichens (\ n).
  • Eine offene Klammer (() muss erneut gefunden werden, gefolgt von 0 oder mehr Zeichen. Dieser Teil sollte die Parameter des Verschlusses enthalten.
  • Wir müssen dann eine schließende Klammer finden ()), gefolgt von 0 oder mehr Zeichen, die optionalen Rückgabetypen sind.
  • Endlich, das im Stichwort sollte gefunden werden.

Wenn die Regulären Ausdruck Objekt kann keine Übereinstimmung finden (z. B. wenn der reguläre Ausdruck nicht gültig ist), rufen wir das auf CompletionHandler mit dem Fehler als Parameter. Wenn in einer Zeile eine Zeichenfolge gefunden wird, die alle diese Bedingungen erfüllt, haben wir eine Schließung korrekt lokalisiert.

Bereinigen Sie die Syntax

Wenn eine Übereinstimmung gefunden wird, rufen wir eine Utility-Methode auf NSString das entfernt die Klammern. Wir müssen auch den Bereich des Matches durchgehen, um zu vermeiden, dass andere Klammern außerhalb des Verschlusses entfernt werden.

Zeilen aktualisieren

Der letzte Teil des Codes überprüft, ob mindestens eine Zeile geändert wurde. Wenn dies wahr ist, rufen wir an setArray () um die neuen Zeilen und die richtigen Indizes zurückzusetzen. Der Completion-Handler wird mit dem Wert aufgerufen Null damit Xcode weiß, dass alles gut gelaufen ist.

Wir müssen das noch umsetzen entfernen (Zeichen: Bereich :) Methode auf NSString. Fügen Sie diese Erweiterung am Anfang der Datei ein.

extension NSString // Entferne die angegebenen Zeichen aus dem Bereich func remove (Zeichen: [Character], im Bereich: NSRange) -> NSString var cleanString = self für Zeichen in Zeichen cleanString = cleanString.replacingOccurrences (of: String (char ), mit: "", Optionen: .caseInsensitiveSearch, range: range) cleanString zurückgeben

Diese Methode ruft auf ersetzeOccurrences (of: with: range :) auf NSString für jedes Zeichen, das wir entfernen möchten.

6. Testen

Xcode 8 bietet eine großartige Lösung zum Testen von Erweiterungen. Vor allem, wenn du rennst OS X 10.11 El Capitan, öffnen Terminal, Führen Sie den folgenden Befehl aus und starten Sie Ihren Mac neu.

Sudo / usr / libexec / xpccachectl

Erstellen Sie anschließend Ihre Erweiterung, und führen Sie sie aus, indem Sie das entsprechende Schema auswählen. Wenn Sie gefragt werden, nach welcher App ausgeführt werden soll, suchen Sie nach Xcode und stellen Sie sicher, dass Sie das auswählen Beta Version von Xcode 8. Eine neue Xcode-Version wird mit grauem Anwendungssymbol gestartet, damit Sie erkennen können, in welcher Instanz von Xcode die Erweiterung getestet wird.

Erstellen Sie in der neuen Xcode-Instanz ein neues Projekt oder öffnen Sie ein vorhandenes und fahren Sie mit fort Editor> Clean Closure> Source Editor-Befehl. Stellen Sie sicher, dass mindestens eine Schließung in der aktuell fokussierten Swift-Datei vorhanden ist, um das Ergebnis anzuzeigen. Wie Sie in der folgenden Animation sehen können, funktioniert unsere Erweiterung.

Quell-Editor-Befehl ist der Standardname für einen Befehl. Sie können es im ändern Info.plist Datei der Erweiterung. Öffnen Sie es und ändern Sie die Zeichenfolge in Syntax reinigen.

Wir können auch eine Verknüpfung zuweisen, um automatisch die Syntax reinigen Befehl. Öffnen Sie Xcodes Einstellungen und wähle das aus Tastenbelegungen Tab. Suchen nach Syntax reinigen und der Befehl wird angezeigt. Klicken Sie rechts daneben und drücken Sie beispielsweise die gewünschte Verknüpfung, Befehl-Alt-Umschalttaste-+. Sie können jetzt zur Quelldatei zurückkehren und diese Verknüpfung drücken, um sie direkt aufzurufen.

7. Tipps und Tricks

Die Erweiterungen von Xcode 8 und Source Editor befinden sich zum Zeitpunkt des Schreibens noch in der Betaphase. Die folgenden Tipps können Ihnen beim Debuggen einiger Probleme helfen, auf die Sie möglicherweise stoßen.

Wenn Ihre Erweiterung in der Xcode-Testinstanz nicht ausgewählt werden kann, beenden Sie das com.apple.dt.Xcode.AttachToXPCService Verarbeiten und führen Sie die Erweiterung erneut aus.

Setzen Sie nur die Zeilen zurück, die Sie im Puffer ändern. Dadurch wird die Erweiterung schneller ausgeführt und die Wahrscheinlichkeit, von Xcode getötet zu werden, ist geringer. Letzteres kann auftreten, wenn Xcode der Meinung ist, dass ein Befehl Ihrer Erweiterung zu lange dauert.

Wenn Sie mehrere Befehle anzeigen möchten, weisen Sie jedem Befehl einen anderen Bezeichner zu und verwenden Sie die commandIdentifier Eigentum an der XCSourceEditorCommandInvocation Objekt, um zu erkennen, welches der Benutzer ausgelöst hat.

Fazit

Das Erstellen der Xcode Source Editor-Erweiterung ist sehr einfach. Wenn Sie Ihren Workflow verbessern und Ihre Entwicklung beschleunigen können, indem Sie eine Quelltexteditorerweiterung erstellen, machen Sie es weiter. Apple hat eine neue Möglichkeit für Entwickler eingeführt, signierte Plugins über den Mac App Store gemeinsam zu nutzen, damit Sie Ihre Arbeit freigeben und beobachten können, wie andere Entwickler davon profitieren.

Den Quellcode des Beispiels dieses Tutorials finden Sie auf GitHub.