Slik oppretter du en Xcode Source Editor Extension

Hva du skal skape

Introduksjon

Xcode er den viktigste IDE (Integrated Development Environment) som brukes av tusenvis av tusenvis av utviklere hver dag. Det er et fantastisk verktøy, men noen ganger vil du tilpasse noen av funksjonene og atferdene for å bedre passe arbeidsflyten din.

Inntil Xcode 7 var det mulig å injisere kode i Xcode ved kjøring for å lage plugins. Plugins kan sendes og distribueres gjennom en flott app kalt Alcatraz. Dette er ikke lenger mulig i Xcode 8.

Xcode 8 validerer hvert bibliotek og bunt for å hindre at ondsinnet kode kjører uten din tillatelse. Når Xcode starter, er ikke tidligere installerte plugins med Alcatraz lastet lenger. Ikke alt går tapt, men Apple annonserte også på WWDC muligheten til å utvikle seg Xcode kilde redaktør utvidelser slik at alle kan utvide eksisterende kildedigeringsfunksjoner. La oss ta en titt på hva vi kan oppnå med slike utvidelser.

1. Komme i gang

Xcode 8 kildeditorutvidelser er et første skritt i riktig retning. Hvis du har jobbet med Xcode for en stund, har du kanskje funnet deg selv i en situasjon der du ønsket at en bestemt oppgave kunne bli automatisert i Xcode. Kildeditorutvidelser tillater tredjepartsprogrammer å modifisere en kildefil, noe som er akkurat det du trenger for å øke hastigheten på arbeidsflyten din.

For øyeblikket kan utvidelser bare samhandle med kildekoden. Dette betyr at ikke alle plugin tilgjengelig gjennom Alcatraz kan erstattes av en kildeditorutvidelse. Men hvem vet hva fremtiden bringer.

Det er viktig å forstå at hver utvidelse må være inneholdt i en macOS-app. Du kan for eksempel legge til innstillinger og forklaringer om hva utvidelsen gjør i MacOS-appen, og distribuere den via Mac App Store. Legg også merke til at hver utvidelse går i en separat prosess. Hvis utvidelsen krasjer, vil den ikke krasje Xcode. I stedet vil det vise en melding om at utvidelsen ikke kunne fullføre arbeidet.

Videre utvidelser Har ikke et brukergrensesnitt og de kan bare endre koden direkte når brukeren påkaller kommandoen din. De kan for eksempel ikke løpe i bakgrunnen.

Jeg anbefaler å se WWDC 2016-sesjonen om kildedirektørutvidelser. Ikke bare forklarer du hvordan du kommer i gang med å utvikle Xcode source editor-utvidelser, det viser også tips og snarveier for å få fart på utviklingen.

2. Oversikt

I denne opplæringen skal vi utvikle en utvidelse som rydder opp syntaxen i Swift. Xcode autocompletterer en lukket syntaks med parentesene, men de kan utelates for korthet. Dette er en oppgave som enkelt kan automatiseres ved å pakke den inn i en kildeditorutvidelse.

Den kortere forklaringen på hva vi skal utvikle er en utvidelse som forvandler enhver lukking til den enklere og renere syntaksen. Ta en titt på eksemplet nedenfor.

// Før session.dataTask (med: url) (data, svar, feil) i // Etter session.dataTask (med: url) data, svar, feil i

3. Prosjektoppsett

Det er selvsagt at denne opplæringen krever Xcode 8. Du kan laste den ned fra Apples utviklerwebside. Den kjører både på OS X 10.11 og MacOS 10.12.

Lage en ny OS X prosjekt av type Kakaosøknad og gi den navnet CleanClosureSyntax. Pass på at du har satt prosjektets språk til Fort. Vi vil bruke den nye Swift 3 syntaks i denne opplæringen.

Vi vil forlate macOS-appen tom for nå, og vi kan fokusere på å lage Xcode-kilde-editor-utvidelsen. Fra Fil meny, velg Nytt> Mål ... . I venstre sidefelt velger du OS X og velg Xcode Source Editor Extension fra listen.

Klikk neste og sett Produktnavn til Cleaner. Et nytt mål vil bli opprettet for deg. Klikk Aktiver hvis Xcode spør deg om den nyopprettede Scheme bør aktiveres.

4. Prosjektstruktur

La oss først analysere hva Xcode nettopp har opprettet for oss. Utvid Cleaner mappe for å se innholdet.

Vi vil ikke endre SourceEditorExtension.swift i denne opplæringen, men det kan brukes til å tilpasse utvidelsen ytterligere. De extensionDidFinishLaunching () Metoden kalles så snart utvidelsen er lansert, slik at du kan utføre eventuelle initialiseringer om nødvendig. De commandDefinitions eiendom getter kan brukes hvis du vil dynamisk vise eller skjule bestemte kommandoer.

SourceEditorCommand.swift er høre på forlengelsen. Denne filen er der du vil implementere logikken for utvidelsen. De utføre (med: completionHandler :) Metoden kalles når brukeren starter utvidelsen din. De XCSourceEditorCommandInvocation objekt inneholder a buffer egenskap, som brukes til å få tilgang til kildekoden i den valgte filen. Fullføringshåndtereren skal kalles med verdi nil hvis alt gikk bra, ellers passere det en NSError forekomst.

5. Implementere utvidelsen

Nå som prosjektet inneholder alle de nødvendige målene, er vi klare til å begynne å skrive utvidelsen. For å gjenopprette, ønsker vi å fjerne parentesene fra hvilken som helst nedleggelse i en Swift-fil. Dette kan gjøres i tre trinn:

  • finn linjene som inneholder en lukning
  • fjern de to parantesene fra den aktuelle linjen
  • erstatte den modifiserte linjen

La oss komme i gang.

Vi kan bruke et regex (vanlig uttrykk) for å analysere hver linje med kode og se om den inneholder en nedleggelse. Du kan henvise til Akiels opplæring om Swift og regulære uttrykk hvis du vil lære mer om vanlige uttrykk. Du kan bruke RegExr til å teste dine vanlige uttrykk. Ta en titt på følgende skjermbilde for å se hvordan jeg testet min regex.

Åpen SourceEditorCommand.swift og endre utføre (med: completionHandler :) metode for å se slik ut:

func perform (med invokasjon: XCSourceEditorCommandInvocation, completionHandler: (NSError?) -> Feid) -> Gyldig var updatedLineIndexes = [Int] () // 1. Finn linjer som inneholder en syntax for lukking for lineIndex i 0 ... < 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) 

Finn linjer med lukket syntaks

Vi oppretter og lager først int verdier som vil inneholde linjeindeksene til de modifiserte linjene. Dette skyldes at vi ikke vil erstatte alle linjene. Vi vil bare erstatte linjene som vi endrer.

Vi teller over alle linjene i invocation.buffer objekt og vi prøver å finne en kamp for Vanlig uttrykk gjenstand. Hvis jeg fjerner escaping-tegnene fra regex, ser det ut som følgende:

. * (. +). + I

Denne regexen samsvarer når en streng har følgende egenskaper:

  • Den har en krøllete åpen brakett (), som etterfølges av 0 eller flere tegn, bortsett fra et nytt linjetegn (\ n).
  • En åpen parentes (() må bli funnet igjen, etterfulgt av 0 eller flere tegn. Denne delen skal inneholde parametrene for lukningen.
  • Vi må da finne en avsluttende parentes ()), etterfulgt av 0 eller flere tegn, som er valgfrie returtyper.
  • Endelig, den i søkeord skal bli funnet.

Hvis Vanlig uttrykk objektet mislykkes i å finne en kamp (for eksempel hvis regex ikke er gyldig), kaller vi completionHandler med feilen som en parameter. Hvis en streng som matcher alle disse forholdene er funnet på en linje, har vi riktig lokalisert en nedleggelse.

Ryd opp syntaks

Når en kamp er funnet, kaller vi en verktøymetode på NSString som fjerner parentesene. Vi må også passere i løpet av kampen for å unngå å fjerne noen andre parenteser utenfor lukkingen.

Oppdater linjer

Den siste delen av koden kontrollerer at minst en linje ble endret. Hvis dette er sant, ringer vi setArray () å erstatte de nye linjene og de riktige indeksene. Fullføringsbehandleren kalles med verdien nil slik at Xcode vet at alt gikk bra.

Vi må fortsatt implementere fjerne (tegn: rekkevidde :) metode på NSString. La oss legge til denne utvidelsen øverst på filen.

utvidelse NSString // Fjern de oppgitte tegnene i rekkevidde func remove (tegn: [Tegn], i rekkevidde: NSRange) -> NSString var cleanString = selv for karbon i tegn cleanString = cleanString.replacingOccurrences (av: String ), med: "", alternativer: .caseInsensitiveSearch, rekkevidde: rekkevidde) returnere cleanString

Denne metoden kaller replacingOccurrences (i: med: rekkevidde :) på NSString for hver karakter som vi vil fjerne.

6. Testing

Xcode 8 kommer med en flott løsning for å teste utvidelser. Først av alt, hvis du kjører OS X 10.11 El Capitan, åpen Terminal, Kjør følgende kommando, og start Macen på nytt.

sudo / usr / libexec / xpccachectl

Etter å ha gjort dette, bygg og kjør utvidelsen ved å velge riktig ordning. Når det spør hvilken app som skal kjøre, søk etter Xcode og sørg for å velge beta versjon av Xcode 8. En ny Xcode versjon vil bli lansert med applikasjonsikonet gråtonet slik at du kan gjenkjenne i hvilket tilfelle Xcode du tester utvidelsen.

I den nye Xcode-forekomsten, opprett et nytt prosjekt eller åpne en eksisterende, og gå til Editor> Ren Closure> Source Editor Command. Sørg for at du har minst én lukking i den nåværende fokuserte Swift-filen for å se resultatet. Som du ser i følgende animasjon, fungerer vår utvidelse.

Source Editor Command er standardnavnet for en kommando. Du kan endre det i Info.plist fil av utvidelsen. Åpne den og endre strengen til Rengjør syntaks.

Vi kan også tilordne en snarvei for automatisk å påkalle Rengjør syntaks kommando. Åpne Xcode er Preferanser og velg Nøkkelbindinger fane. Søk etter Rengjør syntaks og kommandoen vises. Klikk til høyre for det og trykk snarveien du vil bruke, for eksempel, Kommando-Alt-Shift-+. Du kan nå gå tilbake til kildefilen og trykke den snarveien for å påkalle den direkte.

7. Tips og triks

Xcode 8 og kilde redaktørutvidelser er fortsatt i beta ved skrivingstidspunktet. Følgende tips kan hjelpe deg med å feilsøke noen problemer du kanskje kjører inn i.

Hvis utvidelsen ikke kan velges i Xcode-test-forekomsten, drep du av com.apple.dt.Xcode.AttachToXPCService behandle og kjør forlengelsen på nytt.

Bare erstatt linjene som du endrer i bufferen. Dette gjør forlengelsen raskere, og det vil få mindre sjanser til å bli drept av Xcode. Sistnevnte kan skje hvis Xcode mener at en kommando for utvidelsen tar for lang tid.

Hvis du vil vise flere kommandoer, tilordne hver kommando en annen identifikator og bruk commandIdentifier eiendom på XCSourceEditorCommandInvocation Motta for å gjenkjenne hvilket brukeren utløste.

Konklusjon

Opprettelse av Xcode Source Editor-utvidelsen er veldig enkelt. Hvis du kan forbedre arbeidsflyten din og øke hastigheten på utviklingen din ved å opprette en kildeditorutvidelse, så fortsett og gjør det skje. Apple introduserte en ny måte for utviklere å dele signerte plugins gjennom Mac App Store, slik at du kan frigjøre arbeidet ditt og se på at andre utviklere drar nytte av det.

Du finner kildekoden til eksemplet på denne veiledningen på GitHub.